强制Unity在使用RegisterTypes时仅注册接口

时间:2017-08-06 17:37:58

标签: c# unity-container

我想注册我的程序集的特定接口,并使用 RegisterTypes 将它们映射到具体类型方法。

他们注册得很好,但结果我也得到了注册为From types的具体类型。

例如,不仅仅将ITenantStore接口映射到TenantStore类,我不仅获得了映射,还将TenantStore映射到TenantStore。

如何仅将接口注册为From类型?或者有一种有效的方法可以删除从一个类到同一个类的注册吗?

修改:这是一个示例代码

var myClasses = AllClasses.FromAssembliesInBasePath().Where(t => t.Namespace.StartsWith("MyProject", StringComparison.OrdinalIgnoreCase));

container.RegisterTypes(myClasses, 
                  WithMappings.FromMatchingInterface, 
                  WithName.Default, 
                  WithLifetime.ContainerControlled, 
                  getInjectionMembers: t => new InjectionMember[]
                  {
                     new Interceptor<InterfaceInterceptor>(),
                     new InterceptionBehavior<LoggingInterceptionBehavior>()
                  });

2 个答案:

答案 0 :(得分:0)

您的容器已从ImplementationType注册到ImplementationType,因为您将参数getLifetimeManagergetInjectionMembers传递到container.RegisterTypes。所以container.RegisterTypes检查 这个参数,如果条件正确,它会在没有类型映射的情况下第二次注册当前类型。它在调用UnityContainerRegistrationByConventionExtensions.RegisterTypeMappings

期间首次使用类型映射注册当前类型
    string name = getName(type);
    var lifetimeManager = getLifetimeManager(type);
    var members = getInjectionMembers(type).ToList();

    // UnityContainerRegistrationByConventionExtensions.RegisterTypeMappings(container, ...) – It's invocation of common registration 
    // for current type to getFromTypes(type). getFromTypes is WithMappings.FromMatchingInterface in your case

    if (lifetimeManager != null || members.Count > 0)
        container.RegisterType(type, name, lifetimeManager, members);

此时我可以建议不要将这两个论点传递给container.RegisterTypes,你就不会重复注册......

答案 1 :(得分:0)

正如@GeorgeAlexandria所说,为什么&#34;重复&#34;出现具体的注册是因为代码是以这种方式编写的。行为是设计的。

这样做的一个原因是避免按惯例注册更改核心逻辑并考虑支持不同场景的一些边缘情况。例如,在Unity中,InjectionMembersLifetimeManger与具体类型相关联。如果未明确注册具体类型,则在重新注册具有不同生命周期管理器和/或注入成员的类型时,这可能会导致意外行为。

在内部,当你打电话

RegisterType<ITenantStore, TenantStore>(new 
    ContainerControlledLifetimeManager(),
    new InjectionMember[]
    {
        new Interceptor<InterfaceInterceptor>(),
        new InterceptionBehavior<LoggingInterceptionBehavior>()
    });

注册了映射,LifetimeManager通过策略与具体类型TenantStore相关联,注入成员策略与具体类型TenantStore相关联。基本上,为具体类型的接口创建映射,并添加指示如何自定义具体类型的构建计划的策略。虽然确切的代码路径略有不同,但我认为它与按惯例注册方法的情况非常相似,其中一个明显不同的是公共注册属性中出现的具体注册。

如果行为导致问题或者只是令人恼火,您可以自己注册课程。如果情况很直接,它可能看起来像这样:

var myClasses = AllClasses.FromAssembliesInBasePath().Where(t => t.Namespace.StartsWith("MyProject", StringComparison.OrdinalIgnoreCase));
foreach (var type in myClasses)
{
    var matchingInterfaceName = "I" + type.Name;
    var interfaceType = type.GetInterfaces().FirstOrDefault(i => string.Compare(i.Name, matchingInterfaceName, StringComparison.Ordinal) == 0);

    if (interfaceType != null)
    {
        container.RegisterType(interfaceType, type, new ContainerControlledLifetimeManager(),
            new InjectionMember[]
            {
                new Interceptor<InterfaceInterceptor>(),
                new InterceptionBehavior<LoggingInterceptionBehavior>()
            });
    }
}

这不是常规方法的代码,但非常天真并且不能正确支持泛型。