强制 Unity 在使用 RegisterTypes 时仅注册接口 [英] Force Unity to register only interfaces when using RegisterTypes

查看:23
本文介绍了强制 Unity 在使用 RegisterTypes 时仅注册接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to register specific interfaces of my assemblies and map them to concrete types, using the RegisterTypes method.

它们注册得很好,但结果我也将具体类型注册为 From 类型.

They get registered well, but as a result I also get the concrete types being registered as From types.

例如,我不仅得到了映射到 TenantStore 类的 ITenantStore 接口,而且还得到了映射到 TenantStore 的 TenantStore.

For example, instead of having just ITenantStore interface mapped to TenantStore class, I get not only that mapping but also TenantStore mapped to TenantStore.

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

How can I register only the interfaces as From types? Or is there a efficient way to delete the registrations going from one class to the same class?

编辑:这是一个示例代码

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>()
                  });

推荐答案

正如@GeorgeAlexandria 所指出的,出现重复"具体注册的原因是因为代码是这样编写的.该行为是设计使然.

As noted by @GeorgeAlexandria the reason why "duplicate" concrete registrations appear is because the code is written that way. The behavior is by design.

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

One reason it's done this way is to avoid registration by convention changing the core logic and to account for some edge cases in supporting different scenarios. For example, in Unity the InjectionMembers and LifetimeManger are associated with the concrete type. If the concrete type is not explicitly registered this can cause unexpected behavior when re-registering types with different lifetime managers and/or injection members.

内部,当你打电话

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

映射被注册,LifetimeManager通过策略与具体类型TenantStore相关联,并且注入成员策略被添加与具体类型相关联租户商店.基本上,为具体类型的接口创建了一个映射,并添加了指示如何为具体类型定制构建计划的策略.尽管确切的代码路径略有不同,但我认为它与按约定注册方法发生的情况非常相似,唯一的明显区别是公共注册属性中出现的具体注册.

a mapping is registered, the LifetimeManager is associated with the concrete type TenantStore via a policy and and the injection members policies are added associated with the concrete type TenantStore. Basically, a mapping is created for the interface to the concrete type and policies are added indicating how to customize the build plan for the concrete type. Although the exact code path is slightly different I think it is very similar to what happens with the registration by convention approach with the one apparent difference being the concrete registration appearing in the public Registrations property.

如果行为导致问题或只是令人恼火,您可以随时自行注册课程.如果情况是直截了当的,它可能看起来像这样:

If the behavior is causing an issue or is just irritating you could always register the classes yourself. If the situation is straight forward it could look like this:

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>()
            });
    }
}

这不是约定方法的更多代码,但是非常幼稚并且不能正确支持泛型.

This isn't much more code the the convention approach but is pretty naive and does not support generics properly.

这篇关于强制 Unity 在使用 RegisterTypes 时仅注册接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆