.NET5 IoC 按名称注册

.NE5 自带的 IoC 不支持命名, 无法实现按名称获取实例. 原来的项目是用 Unity , 在.NET5 里也可以使用:

Program.cs

Host.CreateDefaultBuilder(args)
    //内置 IoC 不支持命名, 所以这里依然使用 Unity Container 做为 IoC 容器
    //https://github.com/unitycontainer/microsoft-dependency-injection
    .UseUnityServiceProvider()

Startup.cs

        /// <summary>
        /// 使用 Unity 替代自带的 IoC, 因为自带的 IoC 不支持命名
        /// </summary>
        /// <param name="container"></param>
        public void ConfigureContainer(IUnityContainer container)
        {
            //加这个会报错...
            //container.AddExtension(new Diagnostic());
...
...
            usl = new UnityServiceLocator(container);
            ServiceLocator.SetLocatorProvider(() => usl);
        }

虽然 Unity 也是微软的项目, 但是终究不是自带的。。。
而且 使用 Diagnostic 会报错, 具体原因没有细找。

新项目我换了种方式:

维护一份名称和类型的映射关系 ,IoC 正常注册。
获取实例的时候, 先用名称获取类型, 在用类型获取实例。

不是很完美,但是能解决问题:

    public static class ServiceExtension
    {

        /// <summary>
        /// 
        /// </summary>
        private static readonly ConcurrentDictionary<string, Type> dic = new();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="service"></param>
        /// <param name="name"></param>
        public static void WithName<T>(this IServiceCollection service, string name, RegistMode mode) where T : class
        {
            WithName(service, typeof(T), name, mode);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="service"></param>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="mode"></param>
        public static void WithName(this IServiceCollection service, Type type, string name, RegistMode mode)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException($"{nameof(name)} 不能为空");

            if (!dic.TryAdd(name.ToUpper(), type))
            {
                throw new InvalidOperationException($"{name} 已经存在,不能重复注册");
            }
            else
            {
                switch (mode)
                {
                    case RegistMode.Singleton:
                        service.AddSingleton(type);
                        break;
                    case RegistMode.Transient:
                        service.AddTransient(type);
                        break;
                    case RegistMode.Scoped:
                        service.AddScoped(type);
                        break;
                    default:
                        service.AddScoped(type);
                        break;
                }
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sp"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static T GetService<T>(this IServiceProvider sp, string name)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException($"{nameof(name)} 不能为空");

            if (dic.TryGetValue(name.ToUpper(), out Type t))
            {
                return (T)sp.GetService(t);
            }
            else
            {
                //throw new InvalidOperationException($"{name} 未注册");
                return default;
            }
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容