3

Unity 3 为自动注册(按惯例注册)提供了新功能,例如:

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

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

container.RegisterType<IMyService, MyService >();

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

请参阅:CodePlex 上的模式和实践

解释为什么要这样做的重要文章是 Jeremy Miller 的 Convention Over Configuration 文章

4

3 回答 3

4

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

于 2013-04-30T17:59:38.887 回答
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 文件有一个优势 - 您可以重新配置系统而无需重新编译它。

于 2013-04-30T12:16:53.967 回答
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 年才能在 Microsoft 的产品中使用它。嗯。我跑题了。

只要遵循在实现程序集中注册默认值的约定,单元测试和调试注册就变得非常容易。

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

于 2013-08-22T22:28:46.430 回答