在下面的简化示例中,我有一个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
}
我正在努力研究如何使用DI和抽象工厂模式来实现我想要的。在MVC应用程序中,这很容易设置 - Controller需要在其构造函数中实现IUnitOfWork和ICarsRepository的实现。我可以使用不同的控制器工厂配置容器,以便为每个Http请求提供相同的DataContext实例。不知怎的,这里似乎正确处理了一次性依赖。
但是我想在Windows服务中使用相同的存储库。这是多线程的,每个线程在启动时都需要访问自己的存储库,每个线程都应该有自己的DataContext / UnitOfWork。但我不知道该怎么做:
我正在尝试做什么的最好方法是什么?
答案 0 :(得分:2)
因此无法为每个线程解析依赖关系
他们可以,事实上,他们应该。您应该在每个线程的开头解析一个新的对象图。不执行此操作意味着您只能使用线程安全依赖项,而在您的情况下则不然。
我不确定如何使用抽象工厂模式
我认为首先,尝试在您的MVC应用程序中定义您的DataContext
作为每个Web请求,并在Windows服务中定义为每个生命周期范围(或您使用的容器中可用的任何内容)。在您的Windows服务中,每个线程都将获得它自己的生命周期范围。定义范围通常允许您在范围结束时放置实例。
我不希望线程必须关心ICarsRepository实现的依赖性是一次性的
您的主管应该关心这一点,但您的业务逻辑不应该。在启动新线程时,您必须拥有一些基础结构代码,允许开始和结束范围,以及解析和使用图形的根类型。此代码应该是组合根的一部分,因此应用程序的其余部分应该对此无动于衷。如果您使用Per Lifetime Scope(或其他一些显式生命周期)注册了某些类型,则容器将知道何时处置实例。基础结构代码只需告诉容器,范围已结束。
我不想让SqlCarsRepository一次性
SqlCarsRepository
应该依赖于一个没有实现IDisposable
的接口,在这种情况下,没有什么可以处理的。它应该是负责处理DataContext
的容器,并且通过适当的注册,您可以执行此操作。
我正在尝试做什么的最好方法是什么?
您的设计听起来很合理,但这里还有其他一些问题,这可能会让您有更多的工作: