Dav*_*New 4 c# dependency-injection ioc-container unity-container repository-pattern
我正在使用使用工作单元模式的存储库:
public BaseRepository(IUnitOfWork unitOfWork, IEntityFactory factory) { ... }
Run Code Online (Sandbox Code Playgroud)
以前我只需要将一个IUnitOfWork实例注入存储库(使用Unity),如下所示:
// Unit of work for the UserDbContext
container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>(new PerResolveLifetimeManager(), new InjectionConstructor(new UserDbContext()));
container.RegisterType<IUserRepository, UserRepository>();
container.RegisterType<ITokenRepository, TokenRepository>();
Run Code Online (Sandbox Code Playgroud)
现在我需要引入另一个存储库,但是这个存储库需要使用以下的不同实例IUnitOfWork:
// Unit of work for the OrderDbContext
container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>(new PerResolveLifetimeManager(), new InjectionConstructor(new OrderDbContext()));
container.RegisterType<IOrderRepository, OrderRepository>();
Run Code Online (Sandbox Code Playgroud)
如何使用Unity明确指定将哪个IUnitOfWork注入哪个存储库?
编辑:
使用Daniel JG的答案,我有以下代码:
container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>(new PerResolveLifetimeManager(), new InjectionConstructor(new UserDbContext()));
container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>("OrderDbContext", new PerResolveLifetimeManager(), new InjectionConstructor(new OrderDbContext()));
container.RegisterType<IUserRepository, UserRepository>();
container.RegisterType<ITokenRepository, TokenRepository>();
container.RegisterType<IOrderRepository, OrderRepository>(
new InjectionConstructor(
new ResolvedParameter<IUnitOfWork>("OrderDbContext"),
new ResolvedParameter<IEntityFactory<Order, int, OrderTbl>>()
)
);
Run Code Online (Sandbox Code Playgroud)
但是抛出了以下异常:
[ResolutionFailedException:依赖项的解析失败,type ="WebTest.Controllers.TestController",name ="(none)".在解决时发生异常:异常是: InvalidOperationException - IUnitOfWork类型没有可访问的构造函数.
UserRepository具体实现:
public class UserRepository : EntityFrameworkRepository<User, UserTbl>, IUserRepository
{
public UserRepository(IUnitOfWork unitOfWork, IEntityFactory<User, UserTbl> factory)
: base(unitOfWork, factory)
{ }
}
Run Code Online (Sandbox Code Playgroud)
我也在注册实体工厂.即:
container.RegisterType<IEntityFactory<User, int, UserTbl>, UserFactory>();
Run Code Online (Sandbox Code Playgroud)
EntityFrameworkUnitOfWork构造函数:
public class EntityFrameworkUnitOfWork : IUnitOfWork
{
public EntityFrameworkUnitOfWork(DbContext context)
{
Context = context;
}
...
}
Run Code Online (Sandbox Code Playgroud)
您可以使用命名注册,因此您可以注册和解析不同口味的IUnitOfWork.
Unity提供了一个未命名的注册(这是默认注册)以及您需要的多个命名注册.因此,您可以将其中一个IUnitOfWork没有名称的注册作为默认注册,并添加另一个命名注册.例如:
container.RegisterType<IUnitOfWork, UnitOfWork>(new PerResolveLifetimeManager(),
new InjectionConstructor(new UserDbContext()));
container.RegisterType<IUnitOfWork, UnitOfWork>("OrderUow",
new PerResolveLifetimeManager(),
new InjectionConstructor(new OrderDbContext()));
Run Code Online (Sandbox Code Playgroud)
使用上面的代码,当您解析实例IUnitOfWork而不指定任何名称时,container.Resolve<IUnitOfWork>您将获得使用UserDbContext的实例.要获取任何命名实例,您需要执行类似操作container.Resolve<IUnitOfWork>("OrderUow"),它将为您提供使用OrderDbContext的实例.(如果要使用命名注册,则始终强制解析传递名称的类型)
剩下的唯一事情是正确连接存储库的注入参数,以便它们获得正确的IUnitOfWork实例.您可以这样做,配置a ResolvedParameter,它允许您为任何依赖项指定命名注册.(见这个问题)
这样,用于连接存储库的代码如下:
container.RegisterType<IUserRepository, UserRepository>();
container.RegisterType<ITokenRepository, TokenRepository>();
container.RegisterType<IOrderRepository, OrderRepository>(new InjectionConstructor(
new ResolvedParameter<IUnitOfWork>("OrderUow"),
//additional dependencies in the OrderRepository constructor, resolved using default Unity registrations
new ResolvedParameter<IEntityFactory<Order,OrderTbl>>()));
Run Code Online (Sandbox Code Playgroud)
请注意,只有在OrderRepository的情况下,我们需要向注册添加额外信息,因此Unity知道IUnitOfWork应该使用指定的命名注册而不是默认注册来解析依赖项.
有了这些注册,假设您有一个具有以下依赖项的类:
public FooClass(IOrderRepository orderRepository, IUserRepository userRepository, ITokenRepository tokenRepository)
{
...
}
Run Code Online (Sandbox Code Playgroud)
双方userRepository并tokenRepository会得到相同的实例IUnitOfWork,其中将要使用的UserDbContext上下文.
orderRepository将获得一个IUnitOfWork使用OrderDbContext上下文的不同实例.
编辑
使用时,new InjectionConstructor您需要考虑要使用的构造函数的所有参数.在您的库,你需要的情况下IUnitOfWork,并IEntityFactory<T1, T2>在构造函数依赖.我已经更新了IOrderRepository上面的注册与我猜测类型的依赖关系IEntityFactory<Order,OrderTbl>(在UserRepository的情况下将是类型IEntityFactory<User, UserTbl>).
要在构造函数中添加额外的依赖项,请添加更多ResolvedParameter<T>或仅添加typeOf(T).请注意,InjectionConstructor需要的参数顺序与您要注册的类型的构造函数中的参数顺序相匹配.
换句话说,如果你有一个像这样的构造函数
public UserRepository(IUnitOfWork unitOfWork, IEntityFactory<User, UserTbl> factory)
: base(unitOfWork, factory)
{ }
Run Code Online (Sandbox Code Playgroud)您可以使用以下两种方法之一添加InjectionConstructor:
container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor(
//Let's assume the Uow was registered as a named registration
new ResolvedParameter<IUnitOfWork>("UserUow"),
//provide information about additional parameters in the constructor
new ResolvedParameter<IEntityFactory<User,UserTbl>>()));
container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor(
//Let's assume the Uow was registered as a named registration
new ResolvedParameter<IUnitOfWork>("UserUow"),
//provide information about additional parameters in the constructor
typeof(<IEntityFactory<User,UserTbl>>)));
Run Code Online (Sandbox Code Playgroud)这有点麻烦,所以我将其中一个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)
{
}
}
Run Code Online (Sandbox Code Playgroud)
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>();
Run Code Online (Sandbox Code Playgroud)
需要存储库的虚拟控制器:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3234 次 |
| 最近记录: |