dependency injection

我们正在构建一个Windows桌面应用程序(不是基于Web的),并尝试提出实现Repository和UnitOfWork Pattern的最佳方法。

在典型的Asp.Net Mvc应用程序中,您的存储库注入数据上下文,服务注入存储库,最后控制器注入服务,如果您没有遇到任何exception,一切都很好,您将提交更改。

在Windows窗体/ wpf应用程序中,建议不要使用单个datacontext( Oren在MSDN上有一个post),所以我们决定在演示者处创建数据上下文。 我们正在使用Linq2SQl,我们有两个不同的数据库可以根据视图使用。

目前我有以下实施方案

public interface IRepository where T : class { IEnumerable Find(Expression<Func> where); T Single(Expression<Func> where); ... } public class Repository : IRepository where T : class { private readonly Table _table; public Repository(DataContext dataContext) { _table = dataContext.GetTable(); } } public Class TodoService :ITodoService { IRepository _todoRepository; public TodoService(DataContext dataContext) { _todoRepository = new Repository(dataContext) } ... } 

}

// UI的演示者

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

}

我想将演示者与服务分离,并希望在请求ITodoService时注入TodoService,但我无法注入数据上下文有两个原因,因为我必须根据数据库做出决定,或者甚至无法在应用程序中维护数据上下文即使我们只有一个数据库是一个Windows应用程序(许多视图一次打开作为应用程序中的选项卡)并且没有数据上下文我无法创建存储库类并且无法注入服务。

关于如何在这种情况下实现解耦的任何想法

  > I cannot inject data context 

但也许你可以注入一个创建上下文和服务的工厂方法

 public class TodoPresenter { private Func dataContextFactory; private Func serviceFactory; // created with new TodoPresenter(DataContextFactory.GetNewContextForDatabase1(), // dc => new TodoService(dc, // new ToDoRepository(dc => new ToDoRepository(dc)))); public TodoPresenter(Func dataContextFactory, Func 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 todoRepository){...} 

与Service和Presenter的集成测试看起来像这样

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

我将datacontext包装在UnitOfWork中。 并且每个呼叫/会话创建一个单元。

你试过在todoservice中创建datacontext吗?

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

// TodoService将拥有其本地datacontext

 public class TodoService :IDisposable { DataContext dataContext; IRepository _todoRepository; public TodoService() { dataContext = DataContextFactory.GetNewContextForDatabase1(); _todoRepository = new Repository(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(); } } }