Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用DI/抽象工厂模式时的依赖项处理_C#_Entity Framework_Dependency Injection_Repository Pattern_Abstract Factory - Fatal编程技术网

C# 使用DI/抽象工厂模式时的依赖项处理

C# 使用DI/抽象工厂模式时的依赖项处理,c#,entity-framework,dependency-injection,repository-pattern,abstract-factory,C#,Entity Framework,Dependency Injection,Repository Pattern,Abstract Factory,在下面的简化示例中,我有一个DataContext和Repository,我认为它的定义相当合理: public interface IUnitOfWork { int SaveChanges(); } public class DataContext : DbContext, IUnitOfWork { public DbSet<Car> Cars { get ; set; } } public interface ICarsRepository {

在下面的简化示例中,我有一个DataContext和Repository,我认为它的定义相当合理:

public interface IUnitOfWork 
{
   int SaveChanges();
}

public class DataContext : DbContext, IUnitOfWork 
{
    public DbSet<Car> Cars { get ; set; }
}

public interface ICarsRepository 
{
    Car Find(int id);
    void Add(Car car);
}

public class SqlCarsRepository : ICarsRepository 
{
    private DataContext  _context;
    public SqlCarsRepository(DataContext context)
    {
       _context = context;
    }

    public Car Find(int id) 
    {
        return _context.Cars.Find(id);
    }

    //etc
}
公共接口IUnitOfWork
{
int SaveChanges();
}
公共类DataContext:DbContext,IUnitOfWork
{
公共数据库集车辆{get;set;}
}
公共接口ICarsRepository
{
车辆查找(int id);
无效添加(汽车);
}
公共类SqlCarsRepository:ICarsRepository
{
私有数据上下文_上下文;
公共SqlCarsRepository(DataContext上下文)
{
_上下文=上下文;
}
公共车辆查找(int id)
{
return\u context.Cars.Find(id);
}
//等
}
我正在努力研究如何使用DI和抽象工厂模式来实现我想要的。在MVC应用程序中,这将很容易设置-控制器需要在其构造函数中实现IUnitOfWork和ICarsRepository的实例。我可以配置容器,使用不同的控制器工厂为每个Http请求提供相同的DataContext实例。不知何故,这里似乎正确地处理了一次性依赖项

但是,我希望在windows服务中使用相同的存储库。这是多线程的,每个线程在启动时都需要访问自己的存储库,每个线程都应该有自己的DataContext/UnitOfWork。但我不知道怎么做:

  • 应用程序的复合根是服务启动时,因此无法解析每个线程的依赖关系(线程按需启动)
  • 我不确定如何使用抽象工厂模式。该线程需要IUnitOfWork和ICarsRepository的实例,但共享相同的DataContext。我可以创建一个抽象工厂,在一次调用中创建这两个函数,并将其传递到线程中,但是我不知道如何处理DataContext。我不希望线程必须关心对ICarsRepository的实现的依赖关系是一次性的。我绝对不想让线程知道ICarsRepository依赖于DataContext,因为这样看来,拥有一个接口似乎毫无意义——线程可能只依赖于SqlCarsRespository
  • 我不想让SqlCarsRepository成为一次性的,并让它处理DataContext,因为可能有其他人在使用DataContext,而它一开始并没有创建它
  • 我认为我可以创建一个CarsService来隐藏IUnitOfWork和ICarsRepository(并使用抽象工厂获取其实例),但我仍然不知道如何处理DataContext依赖关系
做我正在尝试的事情的最佳方式是什么

因此,不能为每个线程解析依赖关系

他们可以,事实上,他们应该这样做。您应该在每个线程的开头解析一个新的对象图。不这样做,意味着您只能使用线程安全依赖项,在您的情况下不是这样

我不确定如何使用抽象工厂模式

我认为,首先,尝试根据MVC应用程序中的Web请求和windows服务中的生存期范围(或容器中可用的任何内容)定义您的
DataContext
。在windows服务中,每个线程都有自己的生存期范围。定义范围通常允许在范围结束时释放实例

我不希望线程必须关心对ICarsRepository的实现的依赖关系是一次性的

你的线程应该关心这一点,但你的业务逻辑不应该。在启动新线程时,您必须拥有一些基础结构代码,这些代码允许启动和结束作用域,以及解析和使用图的根类型。这段代码应该是合成根目录的一部分,因此应用程序的其余部分应该忽略这一点。如果使用每个生存期范围(或其他显式生存期)注册了某些类型,则容器将知道何时处置实例。基础结构代码只需告诉容器作用域已结束

我不想让SqlCarsRepository成为一次性的

SqlCarsRepository
应该依赖于一个不实现
IDisposable
的接口,在这种情况下,没有什么可处理的。它应该是负责处理
DataContext
的容器,通过正确的注册,您可以这样做

做我正在尝试的事情的最佳方式是什么

您的设计听起来很合理,但以下是一些其他的SO问题,这些问题可能会给您带来更多的帮助:


你用的是什么DI容器,还是手工制作的?@Steven:我用的是Castle WindsorThanks这真的很有用。因此,我可以在每个线程启动时为其创建一个完整的独立对象图。但是主线程上的依赖关系的规则将非常不同,因为它们不在这个基于请求的模型中。拥有两个IoC容器实例并将其中一个配置为主线程的图形,然后将另一个配置为线程,这不好吗?Windows服务将是一个不同于YOUR或MVC网站的应用程序。它将是一个单独的过程,并且(当然)将有自己的容器实例。但不仅如此,由于技术不同,此容器将具有不同的配置。例如,在Windows服务中按每个Web请求注册实例是毫无意义的。但是,在同一应用程序域中具有多个容器实例是不好的。这将使一切变得非常复杂。在thread/request开始时,使用单个容器请求一个新的对象图。