ASP.NET CORE 批量注册服务(扩展)

首先感谢博客园的原作者在 https://www.cnblogs.com/ShenNan/p/10256562.html 文中提供绝佳的批量注册解决方案。由一个空的接口IDependency作为标记。在定义类时,除了要继承原接口,还要额外再继承 IDependency。这样这个类的实例就能被文中的批量注册程序识别到并注册。

IDependency.cs 接口如下:

public interface IDependency
{
    
}

这个接口没有定义任何方法,仅供其他类继承,当做标记使用。

例如一个业务接口:

public interface IPerson
{
    string GetName();
    int GetAge();
}

定义一个类,继承上面的业务接口:

public class Person: IPerson, IDependency
{
    public string GetName()
    {
        return "xxx";
    }

    public int GetAge()
    {
        return 100;
    }
}

注意上面的类还继承了 IDependency,这是核心关键。

上面是博客园原文中没有提到的内容。下面是按服务的生命周期,做了一些扩展,用三个接口IScoped、ISingleton、ITransient 替代 IDependency。

定义三个空的接口:

public interface ITransient
{
    
}
public interface IScoped
{
    
}
public interface ISingleton
{
    
}

在编写业务类时,继承上面任一空接口,指定该类的实例将被按哪种方式注册。例如:

public class Person: IPerson, IScoped
{
    public string GetName()
    {
        return "xxx";
    }

    public int GetAge()
    {
        return 100;
    }
}

最后,修改版的批量注册方法扩展,代码如下:

public static IServiceCollection BatchRegisterService(this IServiceCollection services, Assembly[] assemblys, Type baseType)
        {
            
            List<Type> typeList = new List<Type>();  //所有符合注册条件的类集合
            foreach (var assembly in assemblys)
            {
                //筛选当前程序集下符合条件的类
                var types = assembly.GetTypes().Where(t => !t.IsInterface && !t.IsSealed && !t.IsAbstract && baseType.IsAssignableFrom(t));
                if (types != null && types.Count() > 0)
                    typeList.AddRange(types);
            }
            if (typeList.Count() == 0)
                return services;

            var typeDic = new Dictionary<Type, Type[]>(); //待注册集合
            foreach (var type in typeList)
            {
                var interfaces = type.GetInterfaces();   //获取接口
                typeDic.Add(type, interfaces);
            }
            if (typeDic.Keys.Count() > 0)
            {
                string baseTypeName = baseType.Name;
                foreach (var instanceType in typeDic.Keys)
                {
                    foreach (var interfaceType in typeDic[instanceType])
                    {
                        //根据指定的生命周期进行注册
                        switch (baseTypeName)
                        {
                            case "IScoped":
                                services.AddScoped(interfaceType, instanceType);
                                break;
                            case "ISingleton":
                                services.AddSingleton(interfaceType, instanceType);
                                break;
                            case "ITransient":
                                services.AddTransient(interfaceType, instanceType);
                                break;
                        }
                    }
                }
            }
            return services;
        }

在 Startup.cs 中的调用方法:

services.BatchRegisterService(new Assembly[] { Assembly.GetExecutingAssembly() }, typeof(IScoped));
services.BatchRegisterService(new Assembly[] { Assembly.GetExecutingAssembly() }, typeof(ISingleton));
services.BatchRegisterService(new Assembly[] { Assembly.GetExecutingAssembly() }, typeof(ITransient));


2022-01-14 ASP.NET CORE

发布评论