zoukankan      html  css  js  c++  java
  • Unity容器声明周期管理

    Having said that, here is a solution that you can use with the Unity container:

    Create some custom attributes for the different lifetime styles that you want to have like this:

    [AttributeUsage(AttributeTargets.Class)]
    public class SingletonAttribute : Attribute
    {
    
    }
    
    [AttributeUsage(AttributeTargets.Class)]
    public class TransientAttribute : Attribute
    {
    
    }

    You can have these attributes in some common library and reference it from your service class libraries.

    Then, apply these attributes to your service classes in your class libraries like in your question:

    [Singleton]
    public class ServiceImplA : IService
    {}
    
    [Transient]
    public class ServiceImplB : IService
    {}

    Now, define a helper method that can get the lifetime manager based on reflection like this:

    public static LifetimeManager GetLifeTimeManager<T>()
    {
        Type type = typeof (T);
    
        if(type.GetCustomAttribute(typeof(TransientAttribute)) != null)
            return new TransientLifetimeManager();
    
        if (type.GetCustomAttribute(typeof(SingletonAttribute)) != null)
            return new ContainerControlledLifetimeManager();
    
        //Add more cases here
    
        return new TransientLifetimeManager(); //Default is transient
    }

    And use it like this:

    container.RegisterType<IService, ServiceImplA>(GetLifeTimeManager<ServiceImplA>());

    By the way, this solution is DI container independent. I mean that the attributes themselves are not specific to any container. It is the GetLifeTimeManager helper method that is specific to the Unity container. But you can use other DI containers and define similar helper methods for them.

    You can also create extension methods to hide the invocation of the helper method like this:

    public static IUnityContainer RegisterTypeWithLifeTime<TFrom, TTo>(this IUnityContainer container) where TTo : TFrom
    {
        return container.RegisterType<TFrom, TTo>(GetLifeTimeManager<TTo>());
    }

    And use it like this:

    container.RegisterTypeWithLifeTime<IService, ServiceImplA>();

    You just need to constrain the types returned to types that are annotated with the Singletonattribute:

    container.RegisterTypes(
        AllClasses.FromLoadedAssemblies()
            .Where(t => t.GetCustomAttributes<SingletonAttribute>(true).Any()),
        WithMappings.FromMatchingInterface,
        WithName.Default,
        WithLifetime.ContainerControlled);

    You could register everything and then overwrite the registration for any singletons with a ContainerControlledLifetimeManager:

    // Register All Types by Convention by default
    container.RegisterTypes(
        AllClasses.FromLoadedAssemblies(),
        WithMappings.FromMatchingInterface,
        WithName.Default,
        WithLifetime.Transient);
    
    // Overwrite All Types marked as Singleton
    container.RegisterTypes(
        AllClasses.FromLoadedAssemblies()
            .Where(t => t.GetCustomAttributes<SingletonAttribute>(true).Any()),
        WithMappings.FromMatchingInterface,
        WithName.Default,
        WithLifetime.ContainerControlled,
        null,
        true); // Overwrite existing mappings without throwing

    Another Container:

    using System;
    using System.Reflection;
    using SimpleInjector.Advanced;
    
    // Attribute for use by the application
    public enum CreationPolicy { Transient, Scoped, Singleton }
    
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,
        Inherited = false, AllowMultiple = false)]
    public sealed class CreationPolicyAttribute : Attribute {
        public CreationPolicyAttribute(CreationPolicy policy) {
            this.Policy = policy;
        }
    
        public CreationPolicy Policy { get; private set; }
    }
    
    // Custom lifestyle selection behavior
    public class AttributeBasedLifestyleSelectionBehavior : ILifestyleSelectionBehavior {
        private const CreationPolicy DefaultPolicy = CreationPolicy.Transient;
    
        public Lifestyle SelectLifestyle(Type serviceType, Type implementationType) {
            var attribute = implementationType.GetCustomAttribute<CreationPolicyAttribute>()
                ?? serviceType.GetCustomAttribute<CreationPolicyAttribute>();
    
            switch (attribute != null ? attribute.Policy : DefaultPolicy) {
                case CreationPolicy.Singleton: return Lifestyle.Singleton;
                case CreationPolicy.Scoped: return Lifestyle.Scoped;
                default: return Lifestyle.Transient;
            }
        }
    }
    
    // Usage
    var container = new Container();
    container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
    
    container.Options.LifestyleSelectionBehavior =
        new AttributeBasedLifestyleSelectionBehavior();
    
    container.Register<IUserContext, AspNetUserContext>();
    
    // Usage in application
    [CreationPolicy(CreationPolicy.Scoped)]
    public class AspNetUserContext : IUserContext {
        // etc
    }
  • 相关阅读:
    Hologres如何支持亿级用户UV计算
    飞猪基于 Serverless 的云+端实践与思考
    高德打车构建可观测性系统实践
    程序员写好技术文章的几点小技巧
    配置审计(Config)变配报警设置
    进入中国内地第31年的麦当劳 ,为什么还能不断吸引新消费人群?
    OceanBase再破纪录!核心成员陈萌萌:坚持HTAP就是坚持我们做数据库的初心
    找出有序数组中缺失的数字
    删除值重复的结点
    想交链表----若有缘 必相见
  • 原文地址:https://www.cnblogs.com/lenmom/p/8610685.html
Copyright © 2011-2022 走看看