Unity: Change default lifetime manager for implicit registrations and/or disable them

后端 未结 2 404
忘了有多久
忘了有多久 2020-12-11 01:34

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 proble

相关标签:
2条回答
  • 2020-12-11 02:15

    Is there a way I can either specify a different default lifetime manager

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

    or disable the default auto-resolution behavior completely and limit the container to types I register myself

    Yes, a container extension can do this as well.

    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>();
    
    0 讨论(0)
  • 2020-12-11 02:24

    I tried the DefaultLifetimeManegerExtension but somehow it didnt work. (Maybe Unity has changed?). Anyways if you dont want to use an Extension you can also make use of the RegsiterByConvention feature.

    container.RegisterTypes(AllClasses.FromLoadedAssemblies(), WithMappings.None, WithName.Default, x => new DisposingTransientLifetimeManager());
    

    This will register all Classes with the "DisposingTransientLifetimeManager" which I chose to use as a default one. Note that you should do this at the beginning of your registrations since all registrations will overwrite any previous registrations of the same Type and Name.

    0 讨论(0)
提交回复
热议问题