本文介绍了依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在典型的Asp.Net Mvc应用程序中,您的存储库注入数据上下文,服务注入存储库,最后控制器注入服务,一切都很好,如果你不会有任何异常,您将承担更改。



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



目前我有以下实现

  public interface IRepository&T ;其中T:class 
{
IEnumerable< T> Find(表达式< Func< T,bool>>>其中);
T Single(Expression< Func< T,bool>>其中);
...
}

public class Repository< T> :IRepository< T>其中T:class
{
private readonly Table< T> _表;

public Repository(DataContext dataContext)
{
_table = dataContext.GetTable< T>();
}
}

public Class TodoService:ITodoService
{
IRepository&Todd& _todoRepository;
public TodoService(DataContext dataContext)
{
_todoRepository = new Repository&Todo>(dataContext)
}
...
}

}



// UI的演示者

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

}



我想要将Presenter与服务脱钩,并且在请求ITodoService时要注入TodoService,但是由于两个原因我不能注入数据上下文,因为我必须根据数据库来决定,甚至不能维护数据上下文,即使我们只有一个数据库是一个Windows应用程序(许多视图作为应用程序中的选项卡一次打开),并且没有数据上下文,我无法创建Repository类,也不能注入服务。



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

解决方案
 >我不能注入数据上下文

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

  public class TodoPresenter 
{
private Func< DataContext> dataContextFactory;
private Func< DataContext,ITodoService>服务工厂;

//用新的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 =服务工厂(DataContext的);
// ...
//service.Save(..);
//dataContext.SubmitChanges();
}

}
}

更新



该服务需要一个工厂来获取存储库

  public TodoService(DataContext dataContext,
Func< DataContext,IRepository&Todo> todoRepository){...}

与服务和演示者的集成测试看起来像这样

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


We are builing a windows desktop application (not web based) and trying to come up with the best way to implement Repository and UnitOfWork Pattern.

In a typical Asp.Net Mvc application your repositories are injected with data context, services are injected with repositories and finally controllers are injected with services and all is well if you don't hit any exception, you will commit the changes.

In windows forms/wpf applications it is not advisable to use single datacontext ( Oren has a post on this on MSDN) so we have decided to create data context at the presenter. We are using Linq2SQl and we have two different databases to work with based on the view.

Currently I have the following implementation

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

}

// Presenter for the UI

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

}

I would like decouple the presenter from service and would like to inject TodoService when ITodoService is requested, but I cannot inject data context for two reasons, as I have to decide based on the database or can't even maintain a data context at the application level even if we have only one database being a windows application (many views are open at a time as tabs in the app) and with no data context I cannot create Repository classes and can't inject services.

Any idea on how to achieve decoupling in this situation

解决方案
 > I cannot inject data context

but maybe you can inject a factory method that creates the context and the service

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

    }
}

Update

The Service needs a factory to get the repository as well

public TodoService(DataContext dataContext,
         Func<DataContext, IRepository<Todo> todoRepository){...}

An integrationtest with Service and presenter looks like this

  var toDoRepository = new Mock<..>(..);
  var datacontext= new Mock<..>(..);
  var presenter = new TodoPresenter(dc => datacontext,
                  dc => new TodoService(dc, dc2 => toDoRepository ));

An unitest for presenter starts like this

  var TodoService= new Mock<..>(..);
  var datacontext= new Mock<..>(..);
  var presenter = new TodoPresenter(dc => datacontext,
                  dc => TodoService);

这篇关于依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 18:33