如何防止Unity使用AutoRegistration覆盖现有映射

时间:2013-04-30 11:51:14

标签: c# unity-container

Unity 3为AutoRegistration(按公约注册)提供了新功能,例如:

container.RegisterTypes(
    AllClasses.FromLoadedAssemblies(),  //uses reflection
    WithMappings.FromMatchingInterface, //Matches Interfaces to implementations by name
    WithName.Default);

此代码将针对这些接口注册实现其类似命名接口的所有类型。例如,类MyService:IMyService 将自动注册,就像您编写了以下内容一样:

container.RegisterType<IMyService, MyService >();

我的问题:如果我大部分时间都想要这个怎么办,但我想为我的一个接口选择不同的实现,即使存在类似命名的实现?

请参阅:Patterns and practices on CodePlex

一篇重要的文章,解释为什么你想要这样做是杰里米米勒的 Convention Over Configuration article

3 个答案:

答案 0 :(得分:4)

Unity一直使用“最后胜利”规则进行配置。首先在容器上进行自动配置,然后再进行覆盖。最后一组配置(无论它如何发生)将是容器中的配置。

答案 1 :(得分:1)

什么阻止您使用从配置加载的自定义集覆盖自动映射(如果为空,则表示不会覆盖默认映射):

 // have your auto registration
 container.RegisterTypes(
   AllClasses.FromLoadedAssemblies(),  //uses reflection
   WithMappings.FromMatchingInterface, //Matches Interfaces to implementations by name
   WithName.Default);

 // and override it when necessary
 container.LoadConfiguration();

配置

<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
    <register type="IMyService" mapTo="OverriddenServiceImpl" />
</container>
</unity>

<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
        ...nothing, do not override defaults ...
</container>
</unity>

将可选配置移动到XML文件有一个优点 - 您可以重新配置系统而无需重新编译它。

答案 2 :(得分:0)

我最终使用了Wiktor的方法,但稍有不同,因为我无法及时进入.NET 4.5以获得我的解决方案。所以我无法使用自动注册。

相反,我首先使用

加载任何xml配置
container.LoadConfiguration();

重要的是要认识到,在许多情况下,有一个抽象的默认实现,使用%90 +的时间。实际上,通常会使用默认值,除非模拟测试依赖项。因此,最好是注册默认值。

我的团队有一个约定,默认值是由包含默认值的程序集中的注册类注册的。注册类可通过反射发现。通常,接口或抽象类将在不同的契约程序集中。

注册始终包含在保护条款中:

if (!container.IsRegistered<IMyService>())
{
    container.RegisterType<IMyService, MyService>()
}

我还为IUnityContainer添加了一个扩展方法,以使我的开发人员更加简洁

    public static IUnityContainer RegisterIfUnRegistered<TAbstraction, TImplementation>(
         this IUnityContainer container) where TImplementation : TAbstraction 
    {
        if (!container.IsRegistered <TAbstraction>())
        {
            container.RegisterType<TAbstraction, TImplementation>();
        }
        return container; //Make it fluent
    }

这有各种各样的重载,采取命名注册和工厂注册等。

现在,99%的时间都会发现默认实现,但是根据Wiktor的建议,它们可以在xml中被覆盖。

这看起来有点像烟雾和镜子。自动注册通常会有这样的感觉。它已经在Castle Windsor和其他依赖容器框架中可用多年。遗憾的是,我们不得不等待11年才能在微软的产品中使用它。嗯。我离题了。

只要遵循在实现程序集中注册默认值的约定,就可以非常轻松地进行单元测试和调试注册。

但请记住,通过反映程序集或直接调用注册类来执行注册的代码应该非常接近可执行文件中的main方法。这是你的作文根。 See Mark Seeman's blog了解有关依赖注入的更多信息。他写了the book on DI。我强烈推荐这个。