# 书接上文

# 上篇说到利用接口来定义生命周期

# 通过反射获取继承接口的相关实现

# 并以此来完成对应生命周期的注入

# 但随着框架搭建,已经不止业务接口层和业务实现层需要添加到 IOC 了

# 使用仓储模式后还多了仓储接口层和仓储实现层,原有的方法需要扩展

# 结构如下

  • IDataService 业务接口(包含三个生命周期接口)
  • DataService 业务实现
  • IRepository 仓储接口(新增三个生命周期接口)
  • Repository 仓储实现

# 原先的逻辑是定义三个接口在 IDataService 层下

/// <summary>
/// 单例
/// </summary>
public interface ISingleton
{
}
/// <summary>
/// 瞬时
/// </summary>
public interface ITransient
{
}
/// <summary>
/// 作用域
/// </summary>
public interface IScoped
{
}

# 引用关系是不支持仓储层调用业务层的

# 所以必须在仓储接口层也重复添加这三个接口(后续可能优化)

# 扩展之后代码逻辑如下

/// <summary>
/// 自动注入
/// </summary>
public static class AutoDI
{
    /// <summary>
    /// 通过命名空间注入
    /// </summary>
    /// <param name="services"></param>
    /// <param name="namespaceType"></param>
    /// <returns>IServiceCollection</returns>
    public static IServiceCollection AddService(this IServiceCollection services, string namespaceType)
    {
        Type? singletonType = namespaceType == nameof(IDataService) ? typeof(IDataService.DI.ISingleton) : typeof(IRepository.DI.ISingleton);
        Type? transientType = namespaceType == nameof(IDataService) ? typeof(IDataService.DI.ITransient) : typeof(IRepository.DI.ITransient);
        Type? scopedType = namespaceType == nameof(IDataService) ? typeof(IDataService.DI.IScoped) : typeof(IRepository.DI.IScoped);
        if (namespaceType == nameof(IRepository))
        {
            services.AddScoped(typeof(Repository.BaseRepository<>));
        }
        return AddDataServiceOrRepository(services, singletonType, transientType, scopedType);
    }
    /// <summary>
    /// 注入接口和仓储类
    /// </summary>
    /// <param name="services">The <see cref="IServiceCollection"/> 将服务添加到 </param>
    /// <param name="singletonType"> 单例 </param>
    /// <param name="transientType"> 瞬时 </param>
    /// <param name="scopedType"> 作用域 </param>
    /// <returns>IServiceCollection</returns>
    public static IServiceCollection AddDataServiceOrRepository(IServiceCollection services, Type? singletonType, Type? transientType, Type? scopedType)
    {
        // 获取实现了三个生命周期接口的程序集
        var allTypes = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(a => a.GetTypes().Where(t =>
            t.GetInterfaces().Contains(transientType) ||
            t.GetInterfaces().Contains(singletonType) ||
            t.GetInterfaces().Contains(scopedType)));
        //class 的程序集
        var implementTypes = allTypes.Where(x => x.IsClass).ToArray();
        // 接口的程序集
        var interfaceTypes = allTypes.Where(x => x.IsInterface).ToArray();
        foreach (var implementType in implementTypes)
        {
            var interfaceType = interfaceTypes.FirstOrDefault(x => x.IsAssignableFrom(implementType));
            //class 有接口,用接口注入
            if (interfaceType != null)
            {
                // 判断用什么方式注入
                if (interfaceType.GetInterfaces().Contains(singletonType))
                {
                    // 单例
                    services.AddSingleton(interfaceType, implementType);
                }
                else if (interfaceType.GetInterfaces().Contains(transientType))
                {
                    // 瞬时
                    services.AddTransient(interfaceType, implementType);
                }
                else if (interfaceType.GetInterfaces().Contains(scopedType))
                {
                    // 作用域
                    services.AddScoped(interfaceType, implementType);
                }
            }
            else //class 没有接口,直接注入 class
            {
                // 判断用什么方式注入
                if (implementType.GetInterfaces().Contains(singletonType))
                {
                    // 单例
                    services.AddSingleton(implementType);
                }
                else if (implementType.GetInterfaces().Contains(transientType))
                {
                    // 瞬时
                    services.AddTransient(implementType);
                }
                else if (implementType.GetInterfaces().Contains(scopedType))
                {
                    // 作用域
                    services.AddScoped(implementType);
                }
            }
        }
        return services;
    }
}

# Program 注册服务

var builder = WebApplication.CreateBuilder(args);
// 自动注入接口实现类和仓储实现类
builder.Services.AddService(nameof(IDataService));
builder.Services.AddService(nameof(IRepository));

# 需要调用两次并且传入不同命名空间

# 而且代码逻辑有点混乱不是很好阅读

# 优化一下

/// <summary>
/// 自动注入
/// </summary>
public static class AutoDI
{
    /// <summary>
    /// 通过命名空间注入
    /// </summary>
    /// <param name="services"></param>
    /// <param name="namespaceType"></param>
    public static void AddService(this IServiceCollection services, string namespaceType)
    {
        Type singletonType = null;
        Type transientType = null;
        Type scopedType = null;
        switch (namespaceType)
        {
            case nameof(IDataService):
                singletonType = typeof(IDataService.DI.ISingleton);
                transientType = typeof(IDataService.DI.ITransient);
                scopedType = typeof(IDataService.DI.IScoped);
                break;
            case nameof(IRepository):
                singletonType = typeof(IRepository.DI.ISingleton);
                transientType = typeof(IRepository.DI.ITransient);
                scopedType = typeof(IRepository.DI.IScoped);
                services.AddScoped(typeof(Repository.BaseRepository<>));
                break;
            default:
                break;
        }
        services.AddDataServiceOrRepository(singletonType, transientType, scopedType);
    }
    /// <summary>
    /// 注入接口和仓储类
    /// </summary>
    /// <param name="services">The <see cref="IServiceCollection"/> 将服务添加到 </param>
    /// <param name="singletonType"> 单例 </param>
    /// <param name="transientType"> 瞬时 </param>
    /// <param name="scopedType"> 作用域 </param>
    public static void AddDataServiceOrRepository(this IServiceCollection services, Type? singletonType, Type? transientType, Type? scopedType)
    {
        // 获取实现了三个生命周期接口的程序集
        var allTypes = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(a => a.GetTypes().Where(t =>
            t.GetInterfaces().Contains(singletonType) ||
            t.GetInterfaces().Contains(transientType) ||
            t.GetInterfaces().Contains(scopedType)));
        // 实现类的程序集
        var implementationTypes = allTypes.Where(x => x.IsClass).ToArray();
        // 服务接口的程序集
        var serviceTypes = allTypes.Where(x => x.IsInterface).ToArray();
        foreach (var implementationType in implementationTypes)
        {
            var serviceType = serviceTypes.FirstOrDefault(x => x.IsAssignableFrom(implementationType));
            if (implementationType.GetInterfaces().Contains(singletonType))
            {
                // 单例
                services.AddFromLifeTime(serviceType, implementationType, ServiceLifetime.Singleton);
            }
            else if (implementationType.GetInterfaces().Contains(transientType))
            {
                // 瞬时
                services.AddFromLifeTime(serviceType, implementationType, ServiceLifetime.Transient);
            }
            else if (implementationType.GetInterfaces().Contains(scopedType))
            {
                // 作用域
                services.AddFromLifeTime(serviceType, implementationType, ServiceLifetime.Scoped);
            }
        }
    }
    /// <summary>
    /// 通过生命周期注入接口和实现类
    /// </summary>
    /// <param name="services">The <see cref="IServiceCollection"/> 将服务添加到 </param>
    /// <param name="serviceType"> 要注册的服务类型(Interface)</param>
    /// <param name="implementationType"> 服务的实现类型(Class)</param>
    /// <param name="lifetime"> 注入生命周期 </param>
    /// <exception cref="ArgumentOutOfRangeException"></exception>
    /// <returns>IServiceCollection</returns>
    public static IServiceCollection AddFromLifeTime(this IServiceCollection services, Type serviceType, Type implementationType, ServiceLifetime lifetime)
    {
        switch (lifetime)
        {
            // 单例
            case ServiceLifetime.Singleton:
                services.AddSingleton(serviceType ?? implementationType, implementationType);
                break;
            // 瞬时
            case ServiceLifetime.Transient:
                services.AddTransient(serviceType ?? implementationType, implementationType);
                break;
            // 作用域
            case ServiceLifetime.Scoped:
                services.AddScoped(serviceType ?? implementationType, implementationType);
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof(lifetime), lifetime, null);
        }
        return services;
    }
}

# AddService 方法原先是三元运算符,代码可能比较简洁但是不能一目了然

# AddDataServiceOrRepository 修改了部分命名,并且拆出了一个新的方法 AddFromLifeTime

# AddFromLifeTime 根据生命周期枚举来完成对应的注入,无需判断接口是否为空,为空则注入实现类

懂我意思吧

更新于 阅读次数

请我喝茶~( ̄▽ ̄)~*

Tianci 微信支付

微信支付

Tianci 支付宝

支付宝