首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >单位:宣传命名注册

单位:宣传命名注册
EN

Stack Overflow用户
提问于 2011-06-09 10:31:26
回答 2查看 547关注 0票数 1

使用Unity2.0,我注册了IFoo的两个命名接口,映射到两个不同的实现:

代码语言:javascript
复制
Container
   .RegisterType<IFoo, Foo1>("first")
   .RegisterType<IFoo, Foo2>("second");

嗯,我有这样的服务:

代码语言:javascript
复制
public class ServiceImpl : IService {

    public ServiceImpl(IFoo foo, IDependency dep, IJustAnother stuff) { ... }

    public MyValueObject[] FindVOs() { ... }

}

如果希望注册两个命名服务,每个服务依赖于一个IFoo,我编写如下:

代码语言:javascript
复制
 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:

代码语言:javascript
复制
public class CompositeService : IService {

    public ServiceImpl(IService[] services) { _services = services; }

    public MyValueObject[] FindVOs() { 
       return _services.SelectMany(_ => _.FindVOs() ); 
    }
}

我可以这样注册:

代码语言:javascript
复制
Container
   .RegisterType<IService, CompositeService>();

并且联合将在复合构造函数中注入所有已命名的注册。问题是,这种方式只给所有的IService命名。我不能注入IFoo[]而不是IService,因为IFoo只被ServiceImpl使用,而ServiceImplIService的一种特殊实现。这就是为什么我问是否有更好的方式注册他们,避免冗余,在统一。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-07-01 06:50:54

我解决了编写一个UnityContainerExtension (有它自己的BuilderStrategy)的问题,它允许我这样做:

代码语言:javascript
复制
Container
   .RegisterType<IFoo, Foo1>("first")
   .RegisterType<IFoo, Foo2>("second")

   .RegisterType<IService, ServiceImpl>(
       new InjectionPropagator<IFoo>()
   )
;

这样,我不需要为每个命名的IService注册一个新的名为IFoo,对于我来说非常有用,因为我可以在XML文件中添加命名IFoo注册。

票数 0
EN

Stack Overflow用户

发布于 2011-06-09 12:50:34

你在评论中的回答给出了你想要完成的重要线索:

Foo1可以是管理页面的实现,而Foo2可以是普通用户的实现。

您可以通过注册一个InjectionFactory有效地解决这个问题。我能举出的最简短的例子如下:

代码语言:javascript
复制
container.Register<IFoo>(new InjectionFactory(c =>
{
    if (HttpContext.User.IsInRole("SUPERUSERS"))
        return container.Resolve<Foo1>();

    return container.Resolve<Foo2>();
}));

您还可以通过定义一个IFoo的装饰器/代理来解决这个问题。这使您的DI配置更加简洁,但确实需要更多的代码。下面是一个示例:

代码语言:javascript
复制
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;
        }
    }
}

您可以将其配置如下:

代码语言:javascript
复制
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,如果您想要对它进行单元测试,这一点很重要。

我希望这能帮到你。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6291413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档