You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何动态将类类型传递给泛型Repository类完成数据库操作

实现方案

该需求可实现,C# 支持运行时动态构造泛型类型并调用对应方法,以下是两种可直接运行的实现方案:

方案1:反射调用(无需修改现有仓储结构)

适合不想调整现有静态泛型仓储定义的场景,直接通过反射构造泛型类型、调用Add方法。

基础代码对齐你的现有实现:

// 修正你原接口的笔误
public interface IRepository<TEntity> where TEntity : class
{
    Task Add(TEntity entity);
}

// 你现有使用的静态泛型仓储
public static class Repository<TEntity> where TEntity : class
{
    // 模拟Add方法实现,你可以替换成自己的数据库操作逻辑
    public static Task Add(TEntity entity)
    {
        var nameProp = typeof(TEntity).GetProperty("Name");
        Console.WriteLine($"已添加{typeof(TEntity).Name}对象,Name值:{nameProp?.GetValue(entity)}");
        return Task.CompletedTask;
    }
}

// 你的业务模型类
public class UserClass { public string Name { get; set; } }
public class DepartmentClass { public string Name { get; set; } }
public class CategoryClass { public string Name { get; set; } }

动态调用代码:

string condition = "1"; // 替换为你的实际条件
Type entityType;
object entityInstance;

// 根据条件匹配类型、构造对应实例
switch (condition)
{
    case "1":
        entityType = typeof(UserClass);
        entityInstance = new UserClass { Name = "John" };
        break;
    case "2":
        entityType = typeof(DepartmentClass);
        entityInstance = new DepartmentClass { Name = "研发部" };
        break;
    case "3":
        entityType = typeof(CategoryClass);
        entityInstance = new CategoryClass { Name = "数码分类" };
        break;
    default:
        throw new ArgumentOutOfRangeException(nameof(condition), "不支持的条件值");
}

// 动态构造泛型仓储类型,获取Add方法
var genericRepoType = typeof(Repository<>).MakeGenericType(entityType);
var addMethod = genericRepoType.GetMethod("Add", new[] { entityType });

// 执行异步调用
await (Task)addMethod.Invoke(null, new[] { entityInstance });

方案2:非泛型接口重载(性能更高)

适合可以调整现有仓储结构的场景,通过新增非泛型接口避免高频反射开销。

调整后的仓储定义:

// 新增非泛型仓储接口
public interface IRepository
{
    Task Add(object entity);
}

// 泛型仓储实现非泛型接口
public class Repository<TEntity> : IRepository<TEntity>, IRepository where TEntity : class
{
    // 原有泛型Add方法
    public Task Add(TEntity entity)
    {
        Console.WriteLine($"已添加{typeof(TEntity).Name}对象,Name值:{entity.Name}");
        return Task.CompletedTask;
    }

    // 显式实现非泛型Add,内部做类型转换后调用泛型方法
    Task IRepository.Add(object entity)
    {
        return Add((TEntity)entity);
    }
}

// 简单工厂类,用于获取对应实体的仓储实例
public static class RepositoryFactory
{
    public static IRepository GetRepository(Type entityType)
    {
        var repoType = typeof(Repository<>).MakeGenericType(entityType);
        return (IRepository)Activator.CreateInstance(repoType);
    }
}

// 业务模型类同上
public class UserClass { public string Name { get; set; } }
public class DepartmentClass { public string Name { get; set; } }
public class CategoryClass { public string Name { get; set; } }

调用代码:

string condition = "2"; // 替换为你的实际条件
Type entityType;
object entityInstance;

switch (condition)
{
    case "1":
        entityType = typeof(UserClass);
        entityInstance = new UserClass { Name = "John" };
        break;
    case "2":
        entityType = typeof(DepartmentClass);
        entityInstance = new DepartmentClass { Name = "研发部" };
        break;
    case "3":
        entityType = typeof(CategoryClass);
        entityInstance = new CategoryClass { Name = "数码分类" };
        break;
    default:
        throw new ArgumentOutOfRangeException(nameof(condition), "不支持的条件值");
}

// 直接通过非泛型接口调用
var repo = RepositoryFactory.GetRepository(entityType);
await repo.Add(entityInstance);

注意事项

  • 反射方案如果用于性能敏感场景,可将构造好的addMethod缓存到字典中,避免每次反射的开销
  • 两种方案都要求传入的实体实例与匹配的类型完全对应,否则会抛出类型转换异常
  • 如果你使用依赖注入容器,方案2可以直接从容器中解析对应类型的仓储实例,无需自己实现工厂逻辑

内容的提问来源于stack exchange,提问作者Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 17:15:03