C#如何使用类型变量初始化泛型BaseClass类
问题:通过反射初始化泛型BaseClass并调用其方法
我对Reflection(反射)的理解还很粗浅。
abstract class BaseClass<T> { public abstract T Value { get; } public virtual bool CheckValue(string input) { return true; } } class NotBaseClassA : BaseClass<string> { public override string Value { get => "Yes";} public override bool CheckValue(string input) { return 1 == 2; } } class NotBaseClassB : BaseClass<int> { public override int Value { get => 1; } } class ManyBaseClasses { public NotBaseClassB notBaseClassB; public NotBaseClassA notBaseClassA; } class Programm { public void Main() { foreach (PropertyInfo pi in typeof(ManyBaseClasses).GetProperties()) { string input = Console.ReadLine(); //Get the generic type of the propertyInfo //BaseClass<type> bt = new BaseClass<type>(); //Instantiate BaseClass not as a var So I can do //BaseClass.CheckValue(input) } } }
我正尝试实现目标:使用类型变量初始化泛型BaseClass<T>。我看过相关回答,但返回的是var类型,我无法通过var调用CheckValue()方法(或者我认为不行)。我需要用类型变量对应的正确类型初始化BaseClass<T>,得到一个正式的BaseClass对象而非var,以便调用其方法。
补充说明:我已经通过以下自定义扩展方法获取到了泛型类型变量:
public static System.Type GetBaseClassType(this System.Type type) { System.Type[] types = new System.Type[]{ }; while (type != null && type != typeof(object) || types.Length == 0) { types = type.GetGenericArguments(); if (types.Length > 0) { return types[0]; } type = type.BaseType; } return null; }
解决方案
核心注意点
你原代码里ManyBaseClasses中的是字段(public NotBaseClassB notBaseClassB;),不是属性,所以遍历的时候要用GetFields()而非GetProperties(),这是容易踩的坑。
方案一:引入非泛型基类(推荐)
给泛型BaseClass<T>添加一个非泛型抽象基类,让所有子类能统一向上转型,直接调用CheckValue方法:
// 添加非泛型基类,定义通用方法 public abstract class BaseClass { public abstract bool CheckValue(string input); } // 修改泛型基类,继承自非泛型基类 abstract class BaseClass<T> : BaseClass { public abstract T Value { get; } public override bool CheckValue(string input) { return true; } }
之后在Main方法中直接转型调用:
class Programm { public void Main() { var manyBaseInst = new ManyBaseClasses(); foreach (FieldInfo fi in typeof(ManyBaseClasses).GetFields()) { string input = Console.ReadLine(); // 获取字段实例 var instance = fi.GetValue(manyBaseInst); // 转为非泛型BaseClass,直接调用方法 if (instance is BaseClass baseObj) { bool checkResult = baseObj.CheckValue(input); // 处理结果,比如输出 Console.WriteLine($"检查结果:{checkResult}"); } } } }
方案二:直接通过反射调用方法(无需修改原类结构)
如果不想改动现有基类结构,直接用反射定位并调用CheckValue方法:
class Programm { public void Main() { var manyBaseInst = new ManyBaseClasses(); foreach (FieldInfo fi in typeof(ManyBaseClasses).GetFields()) { string input = Console.ReadLine(); var instance = fi.GetValue(manyBaseInst); // 获取CheckValue方法,参数类型为string MethodInfo checkMethod = instance.GetType().GetMethod("CheckValue", new[] { typeof(string) }); if (checkMethod != null) { // 调用方法并转换返回值 bool checkResult = (bool)checkMethod.Invoke(instance, new object[] { input }); Console.WriteLine($"检查结果:{checkResult}"); } } } }
关于你的扩展方法
你的GetBaseClassType是用来获取泛型参数T的,但在调用CheckValue的场景下完全不需要用到它。如果后续需要处理Value属性,再结合这个方法获取泛型类型,通过反射读取属性值即可。
内容的提问来源于stack exchange,提问作者Logane Ramez
相关产品推荐
相关产品推荐

