你可以使用
命名注册,这样你就可以注册和解决不同的
风味IUnitOfWork
。
Unity允许单个未命名注册(默认注册)和尽可能多的命名注册。因此,你可以将其中一个
IUnitOfWork
注册保留为默认注册,然后添加另一个命名注册。例如:
container.RegisterType<IUnitOfWork, UnitOfWork>(new PerResolveLifetimeManager(),
new InjectionConstructor(new UserDbContext()));
container.RegisterType<IUnitOfWork, UnitOfWork>("OrderUow",
new PerResolveLifetimeManager(),
new InjectionConstructor(new OrderDbContext()));
使用上面的代码,当您解析
IUnitOfWork
实例时,如果不指定任何名称,例如
container.Resolve<IUnitOfWork>
,则会得到使用
UserDbContext的实例。要获取任何命名实例,您需要执行类似于
container.Resolve<IUnitOfWork>("OrderUow")
的操作,这将为您提供使用
OrderDbContext的实例。(当您想要使用命名注册时,始终必须通过传递名称来解决类型)
唯一剩下的事情是正确连接注入参数以获取您的存储库所需的
IUnitOfWork
实例。您可以配置一个
ResolvedParameter
来进行配置,它允许您为任何依赖项指定命名注册。(请参见
此SO问题)
这样,连接您的存储库的代码如下所示:
container.RegisterType<IUserRepository, UserRepository>();
container.RegisterType<ITokenRepository, TokenRepository>();
container.RegisterType<IOrderRepository, OrderRepository>(new InjectionConstructor(
new ResolvedParameter<IUnitOfWork>("OrderUow"),
new ResolvedParameter<IEntityFactory<Order,OrderTbl>>()));
请注意,仅在订单存储库的情况下,我们需要在注册中添加额外信息,这样Unity才知道应该使用指定的命名注册而不是默认注册来解析IUnitOfWork依赖项。有了这些注册,假设您有一个具有以下依赖关系的类:
public FooClass(IOrderRepository orderRepository, IUserRepository userRepository, ITokenRepository tokenRepository)
{
...
}
编辑
在使用new InjectionConstructor
时,您需要考虑要使用的构造函数的所有参数。在您的仓库中,构造函数中有IUnitOfWork
和IEntityFactory<T1, T2>
作为依赖项。我已经更新了IOrderRepository
的注册,假设它具有IEntityFactory<Order,OrderTbl>
类型的依赖项(对于UserRepository而言,这将是IEntityFactory<User, UserTbl>
类型)。
如果要在构造函数中添加额外的依赖项,请添加更多的ResolvedParameter<T>
或只需typeOf(T)
。请注意,在InjectionConstructor
中的参数顺序需要与正在注册的类型的构造函数中的参数顺序匹配。
In other words, if you have a constructor like
public UserRepository(IUnitOfWork unitOfWork, IEntityFactory<User, UserTbl> factory)
: base(unitOfWork, factory)
{ }
You would add an InjectionConstructor in one of these 2 ways:
container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor(
new ResolvedParameter<IUnitOfWork>("UserUow"),
new ResolvedParameter<IEntityFactory<User,UserTbl>>()));
container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor(
new ResolvedParameter<IUnitOfWork>("UserUow"),
typeof(<IEntityFactory<User,UserTbl>>)));
这有点繁琐,所以我建议将其中一个UnitOfWork注册为默认值,这样你就不需要在使用默认UnitOfWork的存储库上使用InjectionConstructor。
编辑2 - 示例代码
虚拟接口和实现:
public class DbContext
{
public string Name { get; set; }
}
public interface IUnitOfWork
{
DbContext DbContext { get; }
}
public class UnitOfWork : IUnitOfWork
{
private readonly DbContext _dbContext;
public UnitOfWork(DbContext dbContext)
{
_dbContext = dbContext;
}
public DbContext DbContext { get { return _dbContext; } }
}
public interface IOrderRepository
{
IUnitOfWork UnitOfWork { get;}
}
public class BaseRepository
{
private readonly IUnitOfWork _uow;
public BaseRepository(IUnitOfWork uow)
{
_uow = uow;
}
public IUnitOfWork UnitOfWork { get { return _uow; } }
}
public class OrderRepository : BaseRepository, IOrderRepository
{
private IFooAdditionalDependency _foo;
public OrderRepository(IUnitOfWork uow, IFooAdditionalDependency foo)
: base(uow)
{
_foo = foo;
}
}
public interface IFooAdditionalDependency { }
public class FooAdditionalDependency : IFooAdditionalDependency
{
}
public interface IUserRepository
{
IUnitOfWork UnitOfWork { get; }
}
public class UserRepository : BaseRepository, IUserRepository
{
public UserRepository(IUnitOfWork uow)
: base(uow)
{
}
}
public interface ITokenRepository
{
IUnitOfWork UnitOfWork { get; }
}
public class TokenRepository : BaseRepository, ITokenRepository
{
public TokenRepository(IUnitOfWork uow)
: base(uow)
{
}
}
Unity容器注册:
container.RegisterType<IUnitOfWork, UnitOfWork>(new PerResolveLifetimeManager(),
new InjectionConstructor(new DbContext{Name = "UserDB"}));
container.RegisterType<IUnitOfWork, UnitOfWork>("OrderDbContext",
new PerResolveLifetimeManager(),
new InjectionConstructor(new DbContext { Name = "OrderDB" }));
container.RegisterType<IUserRepository, UserRepository>();
container.RegisterType<ITokenRepository, TokenRepository>();
container.RegisterType<IOrderRepository, OrderRepository>(new InjectionConstructor(
new ResolvedParameter<IUnitOfWork>("OrderDbContext"),
typeof(IFooAdditionalDependency)));
container.RegisterType<IFooAdditionalDependency, FooAdditionalDependency>();
虚拟控制器需要这些存储库:
public class HomeController : Controller
{
public HomeController(IOrderRepository orderRepository, IUserRepository userRepository, ITokenRepository tokenRepository)
{
Debug.WriteLine("Order repository context: {0}, User repository context:{1}", orderRepository.UnitOfWork.DbContext.Name, userRepository.UnitOfWork.DbContext.Name);
Debug.WriteLine("Order repository context: {0}, User repository context:{1}", orderRepository.UnitOfWork.DbContext.GetType().Name, userRepository.UnitOfWork.DbContext.GetType().Name);
Debug.Assert(orderRepository.UnitOfWork != userRepository.UnitOfWork);
Debug.Assert(userRepository.UnitOfWork == tokenRepository.UnitOfWork);
}
public ActionResult Index()
{
return View();
}
}
UserRepository
的构造函数吗? - Daniel J.G.InjectionConstructor
注册类型时,您需要考虑构造函数中Unity将使用的其他依赖项。这很麻烦,而且不太容易重构,因此我会将一个IUnitOfWork
的注册作为默认注册(例如User和Token存储库的注册),并为其他存储库(在该示例中为OrderRepository)使用命名注册和InjectionConstructor
。 - Daniel J.G.