Внедрение зависимости - PullRequest
3 голосов
/ 02 марта 2011

Мы создаем настольное приложение для Windows (не на веб-основе) и пытаемся найти лучший способ реализации репозитория и шаблона UnitOfWork.

В типичном приложении Asp.Net Mvc ваши репозитории внедряются с контекстом данных, сервисы внедряются с репозиториями, и, наконец, контроллеры внедряются с сервисами, и все хорошо, если вы не нажмете ни одного исключения, вы совершитеперемены.

В приложениях windows form / wpf не рекомендуется использовать один текстовый текст данных ( Oren имеет сообщение об этом в MSDN), поэтому мы решили создать контекст данных у докладчика.Мы используем Linq2SQl, и у нас есть две разные базы данных для работы на основе представления.

В настоящее время у меня есть следующая реализация

public interface IRepository<T> where T : class
    {
        IEnumerable<T> Find(Expression<Func<T, bool>> where);
        T Single(Expression<Func<T, bool>> where);
        ...
     }

public class Repository<T> : IRepository<T> where T : class
    {
        private readonly Table<T> _table;

        public Repository(DataContext dataContext)
        {
            _table = dataContext.GetTable<T>();
        }
   }

public Class TodoService :ITodoService
{
       IRepository<Todo> _todoRepository;
       public TodoService(DataContext dataContext)
       {
           _todoRepository = new Repository<Todo>(dataContext)
       }
       ...
}

}

// Presenter for UI

public class TodoPresenter
{
    public void Save()
    {
       Using (DataContext dataContext = DataContextFactory.GetNewContextForDatabase1())
       {
           ITodoService service = new TodoService(dataContext);
            ...
           service.Save(..);
           dataContext.SubmitChanges();           
       }
    }

}

Я хотел бы отделить докладчика от службы и хотел бы внедрить TodoService, когда запрашивается ITodoService, но я не могу внедрить контекст данных по двум причинам, так как я должен принять решение на основе базы данных или даже не могу поддерживать контекст данных в приложениина уровне, даже если у нас есть только одна база данных, являющаяся приложением Windows (многие представления открываются одновременно как вкладки в приложении), и без контекста данных я не могу создавать классы репозитория и не может внедрять сервисы.

Любая идея о том, как добиться развязки в этой ситуации

Ответы [ 3 ]

2 голосов
/ 03 марта 2011
 > I cannot inject data context

но, возможно, вы можете внедрить фабричный метод, который создает контекст и службу

public class TodoPresenter
{
    private Func<DataContext> dataContextFactory;
    private Func<DataContext, ITodoService> serviceFactory;

    // created with new TodoPresenter(DataContextFactory.GetNewContextForDatabase1(), 
    //                   dc => new TodoService(dc, 
    //                              new ToDoRepository(dc => new ToDoRepository(dc))));
    public TodoPresenter(Func<DataContext> dataContextFactory, 
                         Func<DataContext, ITodoService> serviceFactory)
    {
        this.dataContextFactory = dataContextFactory;
        this.serviceFactory = serviceFactory;
    }

    public void Save()
    {
        using (DataContext dataContext = this.dataContextFactory())
        {
            ITodoService service = serviceFactory(dataContext);
            // ...
            //service.Save(..);
            //dataContext.SubmitChanges();           
        }

    }
}

Обновление

Службе нужна фабрика, чтобы получитьрепозиторий также

public TodoService(DataContext dataContext, 
         Func<DataContext, IRepository<Todo> todoRepository){...}

Тест интеграции с Сервисом и докладчиком выглядит следующим образом

  var toDoRepository = new Mock<..>(..);
  var datacontext= new Mock<..>(..);
  var presenter = new TodoPresenter(dc => datacontext, 
                  dc => new TodoService(dc, dc2 => toDoRepository ));

Единица запуска для докладчика начинается следующим образом

  var TodoService= new Mock<..>(..);
  var datacontext= new Mock<..>(..);
  var presenter = new TodoPresenter(dc => datacontext, 
                  dc => TodoService);
0 голосов
/ 03 марта 2011

вы пытались создать текст данных в todoservice?

public interface IRepository<T> where T : class
{
    IEnumerable<T> Find(Expression<Func<T, bool>> where);
    T Single(Expression<Func<T, bool>> where);
    void Save(T item);
    void SubmitChanges();
}

public class Repository<T> : IRepository<T> where T : class
{
    public void Save(T item)
    {
    }

    public void SubmitChanges()
    {
    }
}

// У TodoService будет свой локальный текстовый текст

public class TodoService :IDisposable
{
   DataContext dataContext;
   IRepository<Todo> _todoRepository;
   public TodoService()
   {
       dataContext = DataContextFactory.GetNewContextForDatabase1();
       _todoRepository = new Repository<Todo>(dataContext);
   }

   public void Dispose()
   {
       dataContext.Dispose();
   }

   void Save(Todo item)
   {
       _todoRepository.Save(item);
   }

   void SubmitChanges()
   {
       _todoRepository.SubmitChanges();
   }
}

// Ведущий

class TodoPresenter
{
    public void Save()
    {
       using (TodoService service = new TodoService())
       {
           Todo item = null;
           // ...
           service.Save(item);
           service.SubmitChanges();           
       }
    }
}
0 голосов
/ 02 марта 2011

Я бы обернул текст данных внутри UnitOfWork.И создайте единицу работы для каждого вызова / сеанса.

...