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

C#如何根据Args实例类型动态创建对应GenericClass泛型实现类实例

实现方案

核心思路是程序启动时一次性扫描程序集构建Args类型到对应实现类的映射缓存,既不用手动维护映射关系,也不会每次调用都遍历类,性能无额外损耗。

第一步:构建全局映射缓存

用静态构造函数实现扫描和缓存,仅执行一次:

using System.Reflection;
using System.Collections.Generic;
using System.Linq;

// 你的包含CreateSpecificInstance方法的类
public class InstanceFactory
{
    // 缓存:Key是Args类型,Value是对应的实现类类型
    private static readonly IReadOnlyDictionary<Type, Type> _argsToImplMap;

    // 静态构造函数:程序首次使用InstanceFactory时自动执行,仅跑一次
    static InstanceFactory()
    {
        var openGenericBase = typeof(GenericClass<>);
        // 按需调整要扫描的程序集,这里默认扫当前程序集,多程序集的话可以传入Assembly数组
        var allCandidateTypes = Assembly.GetExecutingAssembly()
            .GetTypes()
            // 只筛选非抽象的普通类,排除无关类型
            .Where(t => t.IsClass && !t.IsAbstract);

        var map = new Dictionary<Type, Type>();
        foreach (var type in allCandidateTypes)
        {
            var baseType = type.BaseType;
            // 向上查找父类,匹配是否继承自GenericClass<>的闭合泛型类型
            while (baseType != null && baseType.IsGenericType)
            {
                if (baseType.GetGenericTypeDefinition() == openGenericBase)
                {
                    // 取出泛型参数即对应的Args类型
                    var argsType = baseType.GetGenericArguments()[0];
                    map[argsType] = type;
                    break;
                }
                baseType = baseType.BaseType;
            }
        }
        _argsToImplMap = map;
    }

第二步:实现实例创建方法

public object CreateSpecificInstance(ArgsBaseClass args)
    {
        if (args == null) throw new ArgumentNullException(nameof(args));
        var argsType = args.GetType();

        if (!_argsToImplMap.TryGetValue(argsType, out var implType))
        {
            throw new KeyNotFoundException($"未找到对应{argsType.Name}的GenericClass实现类");
        }

        // 直接创建实现类实例,传入args参数
        return Activator.CreateInstance(implType, args);
    }
}

优化建议

  • 如果需要统一调用实例的方法,可以给GenericClass<TArgs>加一个协变非泛型接口/基类,这样返回值可以直接转成接口类型使用,不需要处理动态类型:
    // 定义非泛型基类或者协变接口
    public interface IGenericHandler
    {
        void Execute();
    }
    
    abstract class GenericClass<TArgs> : IGenericHandler where TArgs : ArgsBaseClass
    {
        public abstract void Execute();
    }
    
    // 调用时直接转成接口即可
    public IGenericHandler CreateSpecificInstance(ArgsBaseClass args)
    {
        // 前面逻辑不变
        return (IGenericHandler)Activator.CreateInstance(implType, args);
    }
    
  • 如果实现类分散在多个程序集,只需要修改Assembly.GetExecutingAssembly()部分,传入所有要扫描的程序集即可。
  • 要是扫描范围太大性能不满意,可以给所有实现类加自定义[ArgsImplAttribute],扫描时先筛选带该Attribute的类即可。

原有代码问题修正

你之前写的typeof(args)是语法错误,typeof只能传入类型标识符,获取实例的运行时类型需要调用args.GetType();另外GenericClass是抽象类,不能直接用Activator.CreateInstance实例化,所以不需要先创建泛型基类的实例,直接创建找到的实现类实例即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 21:36:01