WebAPI-程序集

WebAPI-程序集

在Program中,我们注册Service层和Dao层服务过于麻烦,每次添加新的Dao和Service都要注册相应的接口和实现类

可以通过程序集反射的方式,批量注册Service层和Dao层的服务

public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 自动注册服务层中的所有服务。
    /// </summary>
    /// <param name="services">服务集合。</param>
    /// <param name="assembly">包含服务类的程序集。</param>
    /// <returns>配置后的服务集合。</returns>
    public static IServiceCollection AddServices(this IServiceCollection services, Assembly assembly)
    {
        // 获取程序集中的所有命名空间
        var namespaces = GetNamespaces(assembly);

        // 遍历每个命名空间
        foreach (var namespaceName in namespaces)
        {
            // 获取当前命名空间下的所有类型
            var typesInNamespace = assembly.GetTypes()
                .Where(type => type.Namespace == namespaceName);

            // 遍历每个类型
            foreach (var type in typesInNamespace)
            {
                // 查找类型实现的接口
                var interfaceType = type.GetInterfaces()
                    .FirstOrDefault(i => i.Name == $"I{type.Name}");

                // 如果找到了匹配的接口
                if (interfaceType != null)
                {
                    // 将接口和实现类注册为 scoped 服务
                    services.AddScoped(interfaceType, type);
                }
            }
        }

        return services;
    }

    /// <summary>
    /// 自动注册 DAO 层中的所有服务。
    /// </summary>
    /// <param name="services">服务集合。</param>
    /// <param name="assembly">包含 DAO 类的程序集。</param>
    /// <returns>配置后的服务集合。</returns>
    public static IServiceCollection AddDaoServices(this IServiceCollection services, Assembly assembly)
    {
        // 获取程序集中的所有命名空间
        var namespaces = GetNamespaces(assembly);

        // 遍历每个命名空间
        foreach (var namespaceName in namespaces)
        {
            // 获取当前命名空间下的所有类型
            var typesInNamespace = assembly.GetTypes()
                .Where(type => type.Namespace == namespaceName);

            // 遍历每个类型
            foreach (var type in typesInNamespace)
            {
                // 查找类型实现的接口
                var interfaceType = type.GetInterfaces()
                    .FirstOrDefault(i => i.Name == $"I{type.Name}");

                // 如果找到了匹配的接口
                if (interfaceType != null)
                {
                    // 将接口和实现类注册为 scoped 服务
                    services.AddScoped(interfaceType, type);
                }
            }
        }

        return services;
    }

    /// <summary>
    /// 获取程序集中的所有命名空间。
    /// </summary>
    /// <param name="assembly">要检查的程序集。</param>
    /// <returns>包含所有命名空间的集合。</returns>
    private static IEnumerable<string> GetNamespaces(Assembly assembly)
    {
        var namespaces = new HashSet<string>();

        // 遍历程序集中的所有类型
        foreach (var type in assembly.GetTypes())
        {
            // 添加类型所属的命名空间
            namespaces.Add(type.Namespace);
        }

        return namespaces;
    }
}

Program.cs

将Service层和Dao层的程序集作为参数传入到扩展方法

builder.Services.AddServices(typeof(EmployeeService).Assembly);
builder.Services.AddDaoServices(typeof(EmployeeDaoService).Assembly);

EntityConfig

在EFCore中,我们在OnModelCreating方法中会以FluentAPI的方式配置实体类属性和数据表的关系

如果实体类过多,在DBContext文件中代码会过长的问题

在之前讲过,我们可以通过继承IEntityTypeConfiguration<>的方式来为实体类编写配置文件解决这个问题

在OnModelCreating方法中,我们仍然可以通过程序集的方式直接批量注册FluentAPI的配置文件

modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);

DbSet注册

我们需要在DbContext中注册每一个实体类,从而可以通过DbContext操作表

通过程序集反射,可以实现批量注册DbSet的操作

IEntityBase

定义一个接口,让所有的实体类实现这个接口

/// <summary>
/// 实体基类,方便程序集反射使用
/// </summary>
public interface IEntityBase
{
}
OnModelCreatingPartial
void OnModelCreatingPartial(ModelBuilder modelBuilder)
{
    // 获取当前程序集
    var assembly = Assembly.GetExecutingAssembly();

    // 查找所有实现了 IEntity 接口的类型
    var entityTypes = assembly.GetTypes()
        .Where(t => t.IsClass && !t.IsAbstract && typeof(IEntityBase).IsAssignableFrom(t));

    foreach (var entityType in entityTypes)
    {
        // 注册 DbSet
        modelBuilder.Entity(entityType);
    }
}
GetDbSet
// 泛型方法,用于动态获取 DbSet
public DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class, IEntityBase
{
    return Set<TEntity>();
}
使用方法

至此,我们就实现好了DbSet的注册和获取流程,在Dao层直接通过DBContext对象调用GetDbSet()方法即可

var data = _dbContext.GetDbSet<xiaobai_cangqiong_Storage.Entity.User>().Where(u => u.Openid == openid);
// var data = _dbContext.User.Where(u => u.Openid == openid);