3

我們正在建立一個Windows桌面應用程序(而不是基於Web)並試圖想出實現Repository和UnitOfWork模式的最佳方式。依賴注入

在典型的Asp.Net Mvc應用程序中,您的存儲庫注入了數據上下文,服務注入了存儲庫,最後控制器注入了服務,並且一切都很好,如果您沒有遇到任何異常,您將提交更改。

在windows窗體/ 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

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

}

我想解耦服務演示,並會喜歡在ITodoService被請求時注入TodoService,但我不能注入數據上下文有兩個原因,因爲我必須根據數據庫來決定,或者即使我們只有一個數據庫是Windows應用程序,也不能在應用程序級別維護數據上下文(許多視圖一次打開爲應用程序中的選項卡)並且沒有數據上下文我無法創建存儲庫類並且無法注入服務。

如何在這種情況下,實現解耦任何想法

+0

看看這個:http://bit.ly/bF7jL3。 – Steven 2011-03-03 09:59:35

回答

2
> 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){...} 

與服務和主持人的integrationtest看起來像這樣

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

這是_is_依賴注入。我唯一的批評是,傳遞Func <>參數會讓測試設置更復雜一些。我會使用接口和適配器來確保參數是純粹的接口,我可以嘲笑它們進行測試。 – 2011-03-03 05:49:05

+0

k3b:+1,我如何將它擴展到Service,TodoService直接創建TodoRepository,我是否也必須在那裏使用工廠,並將服務的實現傳遞到使用哪個存儲庫?我該如何嘲笑它在整個服務和存儲庫類 – skjagini 2011-03-03 07:11:30

+0

@skjagini:請參閱更新 – k3b 2011-03-03 07:53:20

0

我想包一個的UnitOfWork內DataContext的。並創建一個單位工作或者每個電話/會話。

+0

我沒有使用像wcf這樣的外部服務來封裝每個調用或會話中的數據上下文,它是桌面應用程序,並且在某些情況下(我不想進入),我們直接寫入數據庫服務 – skjagini 2011-03-02 20:41:10

0

您是否嘗試過在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();   
     } 
    } 
} 
+0

1. As數據上下文是在服務內部創建的,如果我的發言人碰巧使用多個服務,我不能在服務間共享數據上下文和提交/回滾更改。 2.不能將TodoService與其他數據庫一起使用,因爲它正在實例化數據上下文。 – skjagini 2011-03-03 05:01:17