使用Unity2.0,我注册了IFoo的两个命名接口,映射到两个不同的实现:
Container
.RegisterType<IFoo, Foo1>("first")
.RegisterType<IFoo, Foo2>("second");嗯,我有这样的服务:
public class ServiceImpl : IService {
public ServiceImpl(IFoo foo, IDependency dep, IJustAnother stuff) { ... }
public MyValueObject[] FindVOs() { ... }
}如果希望注册两个命名服务,每个服务依赖于一个IFoo,我编写如下:
Container
.RegisterType<IService, ServiceImpl>(
"first",
new InjectionConstructor(
new ResolvedParameter<IFoo>("first"),
new ResolvedParameter<IDependency>(),
new ResolvedParameter<IJustAnother>()
)
)
.RegisterType<IService, ServiceImpl>(
"second",
new InjectionConstructor(
new ResolvedParameter<IFoo>("second"),
new ResolvedParameter<IDependency>(),
new ResolvedParameter<IJustAnother>()
)
)它可以工作,但我发现它很难看,也不聪明,因为对于IFoo的每一个新实现,我都需要添加两个RegisterType调用。有没有更好的方法(也许有分机)?
另一个问题:温莎容器是如何处理这一问题的?有自动注册吗?
*编辑*
例如,如果我需要这样的CompositeService:
public class CompositeService : IService {
public ServiceImpl(IService[] services) { _services = services; }
public MyValueObject[] FindVOs() {
return _services.SelectMany(_ => _.FindVOs() );
}
}我可以这样注册:
Container
.RegisterType<IService, CompositeService>();并且联合将在复合构造函数中注入所有已命名的注册。问题是,这种方式只给所有的IService命名。我不能注入IFoo[]而不是IService,因为IFoo只被ServiceImpl使用,而ServiceImpl是IService的一种特殊实现。这就是为什么我问是否有更好的方式注册他们,避免冗余,在统一。
发布于 2011-07-01 06:50:54
我解决了编写一个UnityContainerExtension (有它自己的BuilderStrategy)的问题,它允许我这样做:
Container
.RegisterType<IFoo, Foo1>("first")
.RegisterType<IFoo, Foo2>("second")
.RegisterType<IService, ServiceImpl>(
new InjectionPropagator<IFoo>()
)
;这样,我不需要为每个命名的IService注册一个新的名为IFoo,对于我来说非常有用,因为我可以在XML文件中添加命名IFoo注册。
发布于 2011-06-09 12:50:34
你在评论中的回答给出了你想要完成的重要线索:
Foo1可以是管理页面的实现,而Foo2可以是普通用户的实现。
您可以通过注册一个InjectionFactory有效地解决这个问题。我能举出的最简短的例子如下:
container.Register<IFoo>(new InjectionFactory(c =>
{
if (HttpContext.User.IsInRole("SUPERUSERS"))
return container.Resolve<Foo1>();
return container.Resolve<Foo2>();
}));您还可以通过定义一个IFoo的装饰器/代理来解决这个问题。这使您的DI配置更加简洁,但确实需要更多的代码。下面是一个示例:
using System.Security.Principal;
public class UserBasedFoo : IFoo
{
private readonly IPrincipal currentUser;
private readonly IFoo normalUserFoo;
private readonly IFoo superUserFoo;
public UserBasedFoo(IPrincipal currentUser,
IFoo normalUserFoo, IFoo superUserFoo)
{
this.currentUser = currentUser;
this.normalUserFoo = normalUserFoo;
this.superUserFoo = superUserFoo;
}
object IFoo.FooMethod()
{
return this.CurrentUserFoo.FooMethod();
}
private IFoo CurrentUserFoo
{
get
{
if (this.currentUser.IsInRole("SUPERUSERS"))
return this.superUserFoo;
return this.normalUserFoo;
}
}
}您可以将其配置如下:
container.Register<IPrincipal>(
new InjectionFactory(c => HttpContext.User));
container.Register<IFoo>(new InjectionFactory(c =>
{
return new UserBasedFoo(container.Resolve<IPrincipal>(),
container.Resolve<Foo1>(),
container.Resolve<Foo2>());
}));最后一种方法的缺点是,它是更多的代码,但它更灵活、可重用和可测试。这个类本身不依赖于ASP.NET,如果您想要对它进行单元测试,这一点很重要。
我希望这能帮到你。
https://stackoverflow.com/questions/6291413
复制相似问题