C#中如何使用满足特定约束的未知泛型?求变通方案
解决方案:循环实例化不同泛型参数的Transmission子类
你的核心问题在于泛型类型的编译时约束无法直接在运行时动态类型上生效,但可以通过「非泛型基类型+动态调用/反射」的方式绕过这个限制,不需要手动逐个实例化调用。
步骤1:定义非泛型基接口
先给泛型的Transmission<TTarget, TSource>添加一个非泛型的基接口,用来统一所有Transmission子类的公共成员(比如CommandText),这样我们可以用这个接口作为集合的返回类型:
public interface ITransmission { string CommandText { get; } } // 修改泛型抽象类实现这个接口 public abstract class Transmission<TTargetEntity, TSourceEntity> : ITransmission where TTargetEntity : ClientEntity, new() where TSourceEntity : ClientEntity, new() { public abstract string CommandText { get; } public abstract TTargetEntity CreateTarget(IDataRecord dataRecord); public abstract TSourceEntity CreateSource(TTargetEntity entity); }
步骤2:修正GetTransmissions方法
原来的类型检查逻辑有误(typeof(Transmission)不存在,因为它是泛型类型),需要改为检查类型是否继承自Transmission<,>的泛型定义:
public class TransmissionPlan<T> where T : TransmissionPlan<T> { public static IEnumerable<ITransmission> GetTransmissions() { var baseTransmissionType = typeof(Transmission<,>); // 只遍历公开的实例嵌套类型 foreach (var type in typeof(T).GetNestedTypes(BindingFlags.Public | BindingFlags.Instance)) { // 验证当前类型是否是Transmission<,>的子类 if (type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == baseTransmissionType) { yield return (ITransmission)Activator.CreateInstance(type); } } } }
步骤3:调用泛型Transmit方法
因为Transmit<TTarget, TSource>是泛型方法,直接传入ITransmission编译不通过,有两种可行的调用方式:
方式一:使用dynamic(简洁首选)
用dynamic绕过编译时类型检查,运行时CLR会自动解析正确的泛型参数:
static void Main(string[] args) { foreach (var transmission in MyTransmissionPlan.GetTransmissions()) { Transmit((dynamic)transmission); } }
方式二:使用反射(更灵活但繁琐)
如果需要更精确的控制,可以通过反射获取泛型方法并构造具体的版本调用:
static void Main(string[] args) { var transmitMethod = typeof(Program).GetMethod(nameof(Transmit)); foreach (var transmission in MyTransmissionPlan.GetTransmissions()) { // 获取当前Transmission实例的具体泛型参数 var genericArgs = transmission.GetType().BaseType.GetGenericArguments(); // 构造对应的泛型方法 var specificTransmitMethod = transmitMethod.MakeGenericMethod(genericArgs); // 调用方法 specificTransmitMethod.Invoke(null, new[] { transmission }); } }
额外优化建议
如果Transmit方法的逻辑可以脱离泛型参数实现,建议把核心逻辑移到ITransmission接口或扩展方法中,这样就不需要泛型方法了,进一步简化代码。
内容的提问来源于stack exchange,提问作者Olli
相关产品推荐
相关产品推荐

