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

C#如何将运行时获取的Type对象赋值给泛型参数<T>

问题原因
  • 泛型参数要求编译期确定类型,你直接把运行时获取的Type对象schemaType作为泛型参数传入GetSchemaObjects<>是非法语法,C#编译器无法在编译阶段验证这个类型的合法性,所以会报错。
  • 基类泛型定义存在逻辑错误:类已经声明了泛型参数T,方法GetSchemaObjects<T>又重复声明了同名泛型参数,两个T是完全独立的,会导致实际运行时的类型匹配异常。
  • 方法返回值要求是List<T>,而你运行时动态生成的集合类型是List<schemaType>,编译期无法确认二者的兼容关系,所以会报类型转换错误。
  • 如果iMyInterface接口未声明GetSchemaObjects相关方法,你将实例强转为iMyInterface后也无法直接调用该方法,属于接口契约不匹配。
解决步骤

第一步:修正基类与接口定义

首先修正基类重复声明泛型的问题,同时补全接口契约:

public interface iMyInterface
{
    // 声明非泛型版本方法,方便运行时统一调用
    List<iMyInterface> GetSchemaObjects(string csvData);
}

// 移除方法上重复的泛型声明,直接使用类的泛型参数
public abstract class BaseSchema<T> : iMyInterface where T : iMyInterface
{
    public List<T> GetSchemaObjects(string csvData)
    {
        var records = new List<T>();
        using (var streamReader = new StreamReader(csvData))
        using (var csvReader = new CsvReader(streamReader, CultureInfo.InvariantCulture))
        {
            records = csvReader.GetRecords<T>().ToList();
        }
        return records;
    }

    // 显式实现接口的非泛型方法,做类型转换适配
    List<iMyInterface> iMyInterface.GetSchemaObjects(string csvData)
    {
        return GetSchemaObjects(csvData).Cast<iMyInterface>().ToList();
    }
}

第二步:修改动态调用逻辑

如果需要保留返回强类型List<T>的需求,可以通过反射构造泛型方法调用,修正后的代码如下:

public List<T> GetTestSchema<T>(string versionNumber, string schemaName) where T : iMyInterface
{
    Type[] allSchemaTypes = Assembly.GetExecutingAssembly().GetTypes()
                                    .Where(t => t.IsClass && t.Namespace.StartsWith($"{schemaNamespace}") 
                                            && !t.GetCustomAttributes(typeof(ObsoleteAttribute), true).Any())
                                    .ToArray();            
    int indexNumber = GetIndexNumberOfRequiredVersion(versionNumber);
    Type schemaType = allSchemaTypes
                        .Skip(indexNumber)
                        .Where(x => x.Name.Equals(schemaName) && interfaceType.IsAssignableFrom(x))
                        .FirstOrDefault();
    
    // 提前校验类型兼容性,避免后续转换报错
    if (!typeof(T).IsAssignableFrom(schemaType))
    {
        throw new InvalidOperationException($"查询到的Schema类型{schemaType.Name}与要求的返回类型{typeof(T).Name}不兼容");
    }

    // 创建实例,不需要强转为iMyInterface
    var instance = Activator.CreateInstance(schemaType);
    
    // 反射获取方法并构造闭合泛型方法
    var method = typeof(BaseSchema<>)
                    .MakeGenericType(schemaType)
                    .GetMethod("GetSchemaObjects", BindingFlags.Public | BindingFlags.Instance);
    
    // 调用方法并转换为要求的返回类型
    var result = (List<T>)method.Invoke(instance, new object[] { @"CSV Path" });
    return result;
}
注意事项
  • 如果你不需要返回强类型List<T>,可以直接将方法返回值改为List<iMyInterface>,省去泛型匹配校验和反射构造的步骤,直接调用接口的非泛型方法即可。
  • 确保运行时查询到的schemaType确实继承自BaseSchema<>,否则反射获取方法会抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 13:24:05