[英]Dependency Injection
我們正在構建一個Windows桌面應用程序(不是基於Web的),並嘗試提出實現Repository和UnitOfWork Pattern的最佳方法。
在典型的Asp.Net Mvc應用程序中,您的存儲庫注入數據上下文,服務注入存儲庫,最后控制器注入服務,如果您沒有遇到任何異常,一切都很好,您將提交更改。
在Windows窗體/ wpf應用程序中,建議不要使用單個datacontext( 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的演示者
public class TodoPresenter
{
public void Save()
{
Using (DataContext dataContext = DataContextFactory.GetNewContextForDatabase1())
{
ITodoService service = new TodoService(dataContext);
...
service.Save(..);
dataContext.SubmitChanges();
}
}
}
我想將presenter與服務分離,並希望在請求ITodoService時注入TodoService,但我無法注入數據上下文有兩個原因,因為我必須根據數據庫做出決定,或者甚至無法在應用程序中維護數據上下文即使我們只有一個數據庫是一個Windows應用程序(許多視圖一次打開作為應用程序中的選項卡)並且沒有數據上下文我無法創建存儲庫類並且無法注入服務。
關於如何在這種情況下實現解耦的任何想法
> 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和演示者的集成測試看起來像這樣
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<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將擁有其本地datacontext
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();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.