I've made a document class that downloads and reads the text in it. The smart thing is that it only downloads and reads the text in the document when or if it's needed. By using the Text property it'll try to read the document, if it hasn't been downloaded it'll download it then read it.
It's very nice. However I've noticed my use of Exceptions leads to some funky code. See below.
Document class
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;
}
}
The Problem
What I wrote in the first place.
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;
}
Totally forgetting that the Text property throws an exception. So I have to write something like this, which is a bit funky code.
// 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;
}
I hope you can see what I mean.
So my question, is this a bad design? How would you have done it? Keep in mind I would still like the current functionality.