Unity:更改默认生命周期管理器以进行隐式注册和/或禁用它们

dlf*_*dlf 11 .net c# dependency-injection unity-container

Unity容器将自动解析它可以自己解决的任何类型,而无需手动注册.这在某些方面很好,但我遇到的问题是它使用了TransientLifetimeManager这种类型的分辨率,而我几乎总是想要一个ContainerControlledLifetimeManager.当然,我仍然可以手动将我的类型注册为单身人士,但如果我忘了,而不是在启动时获得未处理的异常,应用程序将成功启动,一切似乎都有效.但是最终会出现一些错误,可能是非常微妙的,难以诊断的错误,因为有一个类型的多个实例意味着单身.

所以我的问题是:有没有办法可以指定不同的默认生命周期管理器或完全禁用默认的自动解析行为,并将容器限制为我自己注册的类型(直接或通过我自己的约定)?

Ran*_*ica 7

有没有办法可以指定不同的默认生命周期管理器

是的,您可以使用将使用不同生命周期管理器的容器扩展.有关示例,请参阅可配置的默认生命周期管理器请求.

或者完全禁用默认的自动解析行为,并将容器限制为我自己注册的类型

是的,容器扩展也可以这样做.

首先在显式注册期间记录注册的BuildKey.然后在创建对象之前检查BuildKey是否已显式注册.

public class RegistrationTrackingExtension : UnityContainerExtension
{
    private ConcurrentDictionary<NamedTypeBuildKey, bool> registrations =
        new ConcurrentDictionary<NamedTypeBuildKey, bool>();

    protected override void Initialize()
    {
        base.Context.Registering += Context_Registering;
        base.Context.Strategies.Add(
            new ValidateRegistrationStrategy(this.registrations), UnityBuildStage.PreCreation);
    }

    private void Context_Registering(object sender, RegisterEventArgs e)
    {
        var buildKey = new NamedTypeBuildKey(e.TypeTo, e.Name);
        this.registrations.AddOrUpdate(buildKey, true, (key, oldValue) => true);
    }

    public class ValidateRegistrationStrategy : BuilderStrategy
    {
        private ConcurrentDictionary<NamedTypeBuildKey, bool> registrations; 

        public ValidateRegistrationStrategy(ConcurrentDictionary<NamedTypeBuildKey, bool> registrations)
        {
            this.registrations = registrations;
        }

        public override void PreBuildUp(IBuilderContext context)
        {
            if (!this.registrations.ContainsKey(context.BuildKey))
            {
                Exception e = new Exception("Type was not explicitly registered in the container.");
                throw new ResolutionFailedException(context.BuildKey.Type, context.BuildKey.Name, e, context);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后添加扩展,注册一些类并解决.如果未明确注册该类,则会抛出异常.

IUnityContainer container = new UnityContainer();
// Add container extension
container.AddNewExtension<RegistrationTrackingExtension>();

// Register types
container.RegisterType<MyClass>();
container.RegisterType<IMyClass, MyClass>();
container.RegisterType<IMyClass, MyClass>("A");

// These succeed because they were explicitly registered
container.Resolve<IMyClass>();
container.Resolve<IMyClass>("A");
container.Resolve<MyClass>();

// MyClass2 was not registered so this will throw an exception
container.Resolve<MyClass2>();
Run Code Online (Sandbox Code Playgroud)