我们正在构建一个windows桌面应用程序(不是基于web的),并试图提出实现存储库和UnitOfWork模式的最佳方法。
在一个典型的Asp.Net Mvc应用程序中,您的存储库被注入数据上下文,服务被注入存储库,最后控制器被注入服务,一切正常如果您没有遇到任何异常,您将提交更改。
在windows forms/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)
}
...
}}
// UI的Presenter
public class TodoPresenter
{
public void Save()
{
Using (DataContext dataContext = DataContextFactory.GetNewContextForDatabase1())
{
ITodoService service = new TodoService(dataContext);
...
service.Save(..);
dataContext.SubmitChanges();
}
}}
我希望将presenter与服务解耦,并希望在请求ITodoService时注入TodoService,但由于两个原因,我无法注入数据上下文,因为我必须基于数据库做出决定,或者甚至无法在应用程序级别维护数据上下文,即使我们只有一个数据库是windows应用程序(许多视图在应用程序中一次打开为选项卡),并且没有数据上下文,我无法创建存储库类,也无法注入服务。
有没有关于如何在这种情况下实现解耦的想法?
发布于 2011-03-03 13:40:39
> 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){...}与Service和presenter的集成测试如下所示
var toDoRepository = new Mock<..>(..);
var datacontext= new Mock<..>(..);
var presenter = new TodoPresenter(dc => datacontext,
dc => new TodoService(dc, dc2 => toDoRepository ));演示者的unitest开始如下所示
var TodoService= new Mock<..>(..);
var datacontext= new Mock<..>(..);
var presenter = new TodoPresenter(dc => datacontext,
dc => TodoService);发布于 2011-03-03 03:58:54
我会将数据上下文包装在UnitOfWork中。并为每个调用/会话创建一个工作单元。
发布于 2011-03-03 12:40:42
您是否尝试过在to服务中创建datacontext?
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();
}
}// presenter
class TodoPresenter
{
public void Save()
{
using (TodoService service = new TodoService())
{
Todo item = null;
// ...
service.Save(item);
service.SubmitChanges();
}
}
}https://stackoverflow.com/questions/5171779
复制相似问题