DotNetCore自带Ioc使用程序集名称注入

ASP.NET Core本身已经集成了一个轻量级的IOC容器,开发者只需要定义好接口后,在Startup.cs的ConfigureServices方法里使用对应生命周期的绑定方法即可, 常用的有如下三种方法:

   services.AddTransient<IApplicationService,ApplicationService> 

services.AddScoped<IApplicationService,ApplicationService>

services.AddSingleton<IApplicationService,ApplicationService> 
  • Transient
    Transient 服务在每次请求时被创建,它最好被用于轻量级无状态服务(如我们的Repository和ApplicationService服务)
  • Scoped
    Scoped 服务在每次请求时被创建,生命周期横贯整次请求
  • Singleton 顾名思义,Singleton(单例) 服务在第一次请求时被创建(或者当我们在ConfigureServices中指定创建某一实例并运行方法),其后的每次请求将沿用已创建服务。如果开发者的应用需要单例服务情景,请设计成允许服务容器来对服务生命周期进行操作,而不是手动实现单例设计模式然后由开发者在自定义类中进行操作。

但是一旦项目变的大 ,要注入的也就很多了,如果一个个添加会十分麻烦,于是可以利用找到程序集里所有需要注入的接口及其实现实现注入。

首先添加一个 IocRegisterAttribute 特性 

using System;

namespace DotNetCoreWeb.Attribute
{
    public class IocRegisterAttribute:System.Attribute
    {
        public Type RegisterType { get; private set; }

        public string Name { get; private set; }

        public IocRegisterAttribute() : this(null, null)
        {
        }

        public IocRegisterAttribute(Type register_type) : this(register_type, null)
        {
        }

        public IocRegisterAttribute(string name) : this(null, name)
        {
        }

        public IocRegisterAttribute(Type registerType, string name)
        {
            this.RegisterType = registerType;
            this.Name = name;
        }
    }
}

其用法是在指定的类上加上,便于搜素程序集时注入需要注入的实例。

下面写具体的通过程序集名称注入方法:使用扩展方法

  

/// <summary>
    /// IServiceCollection扩展
    /// </summary>
    public static class ServiceExtension
    {
        /// <summary>
        /// 用DI批量注入接口程序集中对应的实现类。
        /// <para>
        /// 需要注意的是,这里有如下约定:
        /// IUserService --> UserService, IUserRepository --> UserRepository.
        /// </para>
        /// </summary>
        /// <param name="service"></param>
        /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>
        /// <returns></returns>
        public static IServiceCollection RegisterAssembly(this IServiceCollection service,string[] IocAssemblyNames)
        {
             foreach(var name in IocAssemblyNames){
                 RegisterType(name,service);
             }
            return service;
        }
  

        public static void RegisterType(string assemblyName, IServiceCollection service)
        {
            Type[] types = Assembly.Load(assemblyName).GetTypes();
            foreach (Type type in types)
            {
                System.Attribute[] attrs = System.Attribute.GetCustomAttributes(type);
                foreach (System.Attribute attr in attrs)
                {
                    if (attr is IocRegisterAttribute)
                    {
                        var attribute = attr as IocRegisterAttribute;
                        var baseTypes = new List<Type>();
                        if (attribute.RegisterType != null)
                        {
                            baseTypes.Add(attribute.RegisterType);
                        }
                        else if (type.GetInterfaces().Any())
                        {
                            baseTypes.AddRange(type.GetInterfaces());
                        }
                        if (type.BaseType != null && type.BaseType != typeof (Object))
                        {
                            Type bt = type.BaseType;
                            while (bt.BaseType != null && bt.BaseType != typeof (Object))
                                bt = bt.BaseType;
                            baseTypes.Add(bt);
                        }
                        if (baseTypes.Count <= 0)
                            throw new Exception(string.Format("类型"{0}"没有基类型", type));
                        foreach (Type baseType in baseTypes)
                        { 
                            service.AddTransient(baseType,type);
                        }
                    }
                }
            }
        }

        
    }

只需在Startup中调用

 

IocAssemblyName在appsettiings中定义,如果多个程序集则用','隔开。

原文地址:https://www.cnblogs.com/LIUWEI123/p/8584302.html