本文介绍了Unity:更改隐式注册的默认生命周期管理器和/或禁用它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The Unity container will automatically resolve any type that it can figure out on its own without the need for manual registration. That's good in some ways, but the problem I have is that it uses a TransientLifetimeManager for this type of resolution, while I almost always want a ContainerControlledLifetimeManager. I can still register my types as singletons manually, of course, but if I forget, instead of getting an unhandled exception at startup, the app will launch successfully and everything will appear to work. But there will eventually be bugs, possibly very subtle, hard-to-diagnose ones, due to the fact that there are multiple instances of a type that's meant to be a singleton.

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

So my question is: Is there a way I can either specify a different default lifetime manager or disable the default auto-resolution behavior completely and limit the container to types I register myself (directly or by my own conventions)?

推荐答案

是的,您可以使用将使用不同生命周期管理器的容器扩展。有关示例,请参见。

Yes, you can use a container extension that will use a different lifetime manager. See Request for configurable default lifetimemanager for an example.

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

Yes, a container extension can do this as well.

首先在显式注册过程中记录BuildKey的注册。然后在创建对象之前检查BuildKey是否已被明确注册。

First during explicit registration record the BuildKey of the registration. Then before creating the object check if the BuildKey was explicitly registered.

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

然后添加扩展名,注册一些类并解决。如果类没有明确注册,那么将抛出异常。

Then add the extension, register some classes and resolve. If the class was not explicitly registered then an exception will be thrown.

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

这篇关于Unity:更改隐式注册的默认生命周期管理器和/或禁用它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 20:47