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