Что надлежащий путь состоит в том, чтобы ввести зависимость от доступа к данным для ленивой загрузки?

11
задан George Mauer 24 September 2008 в 22:17
поделиться

3 ответа

Я не ужасно знаком с термином ПОСТЕПЕННО, но определения, которые я прочитал, кажется, обычно следуют за духом объекта, являющегося независимым от некоторой большей платформы.

Тем не менее, неважно, как Вы нарезаете его при выполнении внедрения зависимости Вы собираетесь иметь сотрудничество с теми классами, функциональность которых введена в, и что-то, что засовывает зависевший от объектов в, является ли это полноценной инжекционной платформой или просто некоторым ассемблерным классом.

Мне кажется странным ввести ссылку на контейнер МОК в класс. Я предпочитаю, чтобы мои инжекции произошли в конструкторе с выглядящим примерно так кодом:

public interface IDao<T>
{
    public T GetById(int id);
}


public interface ICustomerDao : IDao<Customer>
{
}

public class CustomerDao : ICustomerDao
{
    public Customer GetById(int id) 
    {...}
}

public class Transaction<T> where T : class
{

    int _id; //Transaction always knows this value
    T _dataObject;
    IDao<T> _dao;

    public Transaction(IDao<T> myDao, int id)
    {
        _id = id;
        _dao = myDao;
    }

    public T Get()
    {
        if (_dataObject == null)
            _dataObject = _dao.GetById(_id);
        return _dataObject;
    }
}
1
ответ дан 3 December 2019 в 10:27
поделиться

Я обычно делаю внедрение зависимости в конструкторе как Вы имеет выше, но берет ленивую загрузку шага вперед путем действия только, когда "получение" называют как, я имею ниже. Не уверенный, если это - чистый подход, Вы ищете, но он действительно устраняет "грязного" конструктора Загрузка DI / Ленивая Загрузка на 1 шаге ;)

public class Product
{
    private int mProductID;
    private Supplier mSupplier;
    private ISupplierService mSupplierService;

    public Product()
    {
      //if you want your object to remain POCO you can use dual constr
      //this constr will be for app use, the next will be for testing
    } 

    public Product(ISupplierService SupplierService)
    {
        mSupplierService = SupplierService;
    }

    public Supplier Supplier {
        get {
            if (mSupplier == null) {
                if (mSupplierService == null) {
                    mSupplierService = new SupplierService();
                }
                mSupplier = mSupplierService.GetSupplierByProductID(mProductID);
            }
            return mSupplier;
        }
        set { mSupplier = value; }
    }
}
1
ответ дан 3 December 2019 в 10:27
поделиться

Я предлагаю что-то другое... Используйте ленивый класс загрузки:

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);
    }
}

После того как Вы получаете его, Вы не должны вводить дао в Вас объект больше:

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
    }
}

При создании объекта Транскатиона, который не связывается с базой данных:

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));
}

Две интересных вещи происходят: - Ваши объекты области могут использоваться с или без доступа к данным, это становится неосведомленным доступом данных. Единственное небольшое скручивание должно включить для передачи функции, которые дают объект вместо самого объекта. - Ленивый класс внутренне изменяем, но может использоваться в качестве неизменного значения. Ключевое слово только для чтения сохраняет свое семантическое, так как его содержание не может быть изменено внешне.

Когда Вы захотите, чтобы поле было перезаписываемо, просто удалите ключевое слово только для чтения. при присвоении нового значения новое Ленивое будет создано с новым значением из-за неявного броска.

Править: Я вел блог об этом здесь:

http://www.thinkbeforecoding.com/post/2009/02/07/Lazy-load-and-persistence-ignorance

7
ответ дан 3 December 2019 в 10:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: