2

テキストをダウンロードして読み取るドキュメントクラスを作成しました。スマートなことは、ドキュメント内のテキストを必要な場合にのみダウンロードして読み取ることです。Text プロパティを使用して、ドキュメントを読み取ろうとします。ダウンロードされていない場合は、ダウンロードしてから読み取ります。

それは非常にうれしいです。ただし、例外を使用すると、ファンキーなコードになることに気付きました。下記参照。

ドキュメント クラス

public delegate byte[] DownloadBinaryDelegate(IDocument document);
public delegate string TextReaderDelegate(IDocument document);

public class Document
{
        public DownloadBinaryDelegate DownloadBinaryDelegate { private get; set; }
        public TextReaderDelegate TextReaderDelegate { private get; set; }

        private bool _binaryIsSet;
        private byte[] _binary;
        public byte[] Binary
        {
            get 
            {
                if (_binaryIsSet)
                    return _binary;

                if (DownloadBinaryDelegate == null)
                    throw new NullReferenceException("No delegate attached to DownloadBinaryDelegate.");

                Binary = DownloadBinaryDelegate(this);
                DownloadBinaryDelegate = null; // unhock delegate as it's no longer needed.

                return _binary;
            }
            set
            {
                if (_binaryIsSet) 
                    return;

                _binary = value;
                _binaryIsSet = true;
            }
        }

        private bool _textIsSet;
        private string _text;
        public string Text
        {
            get
            {
                if (_textIsSet)
                    return _text;

                if (TextReaderDelegate == null)
                    throw new NullReferenceException("No delegate attached to TextReaderDelegate.");

                Text = TextReaderDelegate(this); // this delegate will call Binary and return the translated text.
                TextReaderDelegate = null; // unhock delegate as it's no longer needed.

                return _text;
            }
            set
            {
                if (_textIsSet)
                    return;

                _text = value;
                _textIsSet = true;
            }
        }

問題

最初に書いたこと。

if (document.Text == null) // text is not set
{
    if (document.Binary == null) // binary has not been downloaded
        document.DownloadBinaryDelegate = Util.DownloadDocument;

    document.TextReaderDelegate = Util.ReadDocument;
}

Text プロパティが例外をスローすることを完全に忘れています。だから私はこのようなものを書かなければなりませんが、これはちょっと変わったコードです。

// check if text has already been read and set
try
{
    var isTextSet = document.Text == null;
}
catch (NullReferenceException)
{
    document.DownloadBinaryDelegate = Util.DownloadDocument;
    document.TextReaderDelegate = Util.ReadDocument;
}

私の言いたいことがわかると思います。

私の質問は、これは悪い設計ですか? どうやってそれをしたでしょうか?私はまだ現在の機能が欲しいことを心に留めておいてください。

4

2 に答える 2

2

遅延初期化は、.NET フレームワークに既に組み込まれています。を使用してクラスを再実装することをお勧めしますLazy<T>

あなたの特定の質問に答えるために、あなたのクラスは常にバイナリとテキストのデリゲートを必要とするように聞こえるので、コンストラクターに必須のパラメーターにします。

于 2013-02-27T11:01:13.837 に答える
0

許可されていないデリゲート(this)を使用しているため、Lazyを使用できませんでした。

だから私はここからの素晴らしい答えを使用することになりました:プロパティをnullにできない場合に使用する例外タイプは何ですか?

public class Document
{
    private DownloadBinaryDelegate _downloadBinaryDelegate;
    public void SetDownloadBinaryDelegate(DownloadBinaryDelegate downloadBinary)
    {
        if (downloadBinary == null)
            throw new ArgumentNullException("downloadBinary");

        _downloadBinaryDelegate = downloadBinary;
    }

    private TextReaderDelegate _textReaderDelegate;
    public void SetTextReaderDelegate(TextReaderDelegate readerDelegate)
    {
        if (readerDelegate == null)
            throw new ArgumentNullException("readerDelegate");

        _textReaderDelegate = readerDelegate;
    }

    private bool _binaryIsSet;
    private byte[] _bytes;

    public void SetBinary(byte[] bytes, bool forceOverwrite = false)
    {
        if (_binaryIsSet && !forceOverwrite)
            return;

        _bytes = bytes;
        _binaryIsSet = true;
    }

    public byte[] GetBinary()
    {
        if (_binaryIsSet)
            return _bytes;

        if (_downloadBinaryDelegate == null)
            throw new InvalidOperationException("No delegate attached to DownloadBinaryDelegate. Use SetDownloadBinaryDelegate.");

        SetBinary(_downloadBinaryDelegate(this));
        _downloadBinaryDelegate = null; // unhock delegate as it's no longer needed.

        return _bytes;
    }

    public bool TryGetBinary(out byte[] bytes)
    {
        if (_binaryIsSet)
        {
            bytes = _bytes;
            return true;
        }

        if (_downloadBinaryDelegate != null)
        {
            bytes = GetBinary(); // is this legit?
            return true;
        }

        bytes = null;
        return false;
    }

    private bool _textIsSet;
    private string _text;

    public void SetText(string text, bool forceOverwrite = false)
    {
        if (_textIsSet && !forceOverwrite)
            return;

        _text = text;
        _textIsSet = true;
    }

    public string GetText()
    {
        if (_textIsSet)
            return _text;

        if (_textReaderDelegate == null)
            throw new InvalidOperationException("No delegate attached to TextReaderDelegate. Use SetTextReaderDelegate.");

        SetText(_textReaderDelegate(this)); // this delegate will call Binary and return the read text.
        _textReaderDelegate = null; // unhock delegate as it's no longer needed.

        return _text;
    }

    public bool TryGetText(out string text)
    {
        byte[] bytes;
        if (!TryGetBinary(out bytes))
        {
            text = null;
            return false;
        }

        if (_textIsSet)
        {
            text = _text;
            return true;
        }

        if (_textReaderDelegate != null)
        {
            text = GetText(); // is this legit?
            return true;
        }

        text = null;
        return false;
    }
}
于 2013-02-27T18:59:25.113 に答える