Я предлагаю что-то другое ...
Использовать ленивый класс загрузки:
public class Lazy<T>
{
T value;
Func<T> loader;
public Lazy(T value) { this.value = value; }
public Lazy(Func<T> loader { this.loader = loader; }
T Value
{
get
{
if (loader != null)
{
value = loader();
loader = null;
}
return value;
}
public static implicit operator T(Lazy<T> lazy)
{
return lazy.Value;
}
public static implicit operator Lazy<T>(T value)
{
return new Lazy<T>(value);
}
}
Как только вы его получите, вам больше не нужно вводить dao в ваш объект:
public class Transaction
{
private static readonly Lazy<Customer> customer;
public Transaction(Lazy<Customer> customer)
{
this.customer = customer;
}
public Customer Customer
{
get { return customer; } // implicit cast happen here
}
}
При создании объекта Transcation, который не привязан к базе данных:
new Transaction(new Customer(..)) // implicite cast
//from Customer to Lazy<Customer>..
При регенерации транзакции из базы данных в хранилище:
public Transaction GetTransaction(Guid id)
{
custmerId = ... // find the customer id
return new Transaction(() => dao.GetCustomer(customerId));
}
Происходят две интересные вещи:
- Ваши доменные объекты могут использоваться с доступом к данным или без него, он становится невежественным. Единственный маленький поворот состоит в том, чтобы позволить передать функцию, которая дает объект вместо самого объекта.
- Класс Lazy является внутренне изменяемым, но может использоваться как неизменяемое значение. Ключевое слово readonly сохраняет свою семантику, поскольку его содержимое не может быть изменено извне.
Если вы хотите, чтобы поле было доступно для записи, просто удалите ключевое слово readonly. при назначении нового значения будет создано новое Lazy с новым значением из-за неявного приведения.
Edit:
Я писал об этом здесь:
http://www.thinkbeforecoding.com/post/2009/02/07/Lazy-load-and-persistence-ignorance