当T类型无关紧要时,如何处理泛型DerivedClass<T>类型对象?
问题描述
我有一个无法修改签名的接口函数SetParametersAsync(BaseClass myObject),函数内部通过if/else判断对象类型来调用对应方法。现在要新增泛型类型DerivedClass<T> : BaseClass(T为struct),但T的具体类型无关紧要,希望所有T的该派生类对象都调用同一个方法。
示例代码如下:
// 现有类,无法修改签名 public class ExampleClass : IParameterMethods { // 继承自接口,无法修改签名 public async Task<bool> SetParametersAsync(BaseClass myObject) { if (myObject is MyClassA a) { a.DoThis(); MethodThatExpectsAMyClassAParameter(a); } // ...其他if判断 // 这是我要为新泛型类添加的逻辑(无法编译): else if (myObject is DerivedClass<T> derived) { derived.MethodFromGenericClass(); MethodThatExpectsDerivedClassTParameter(derived); } } // 这个方法要接收泛型对象,T具体类型不重要,只要是struct就行 private void MethodThatExpectsDerivedClassTParameter(DerivedClass<T> derived) where T: struct { // ...逻辑实现 } }
上述代码无法编译,因为T类型未知,且我不想为所有可能的T类型添加if判断,该如何解决?
解决方案
方案1:引入非泛型基接口(推荐)
给DerivedClass<T>提取一个非泛型的基接口,将与T无关的方法定义在接口中,这样就可以在SetParametersAsync里直接判断接口类型,无需关心具体的T。
代码实现
// 新增非泛型接口,定义所有不需要T的方法 public interface IDerivedClass { void MethodFromGenericClass(); } // 修改泛型类,实现该非泛型接口 public class DerivedClass<T> : BaseClass, IDerivedClass where T : struct { public void MethodFromGenericClass() { // 原有方法逻辑 } } // 更新SetParametersAsync的判断逻辑 public async Task<bool> SetParametersAsync(BaseClass myObject) { if (myObject is MyClassA a) { a.DoThis(); MethodThatExpectsAMyClassAParameter(a); } // ...其他if判断 else if (myObject is IDerivedClass derived) { derived.MethodFromGenericClass(); // 如果MethodThatExpectsDerivedClassTParameter不需要依赖T,直接修改其参数为IDerivedClass MethodThatExpectsDerivedClass(derived); } } // 调整方法参数为非泛型接口(如果原方法不需要T的话) private void MethodThatExpectsDerivedClass(IDerivedClass derived) { // ...统一逻辑实现 }
如果MethodThatExpectsDerivedClassTParameter必须依赖DerivedClass<T>实例,可以结合反射调用泛型方法,或者使用下面的方案。
方案2:反射调用泛型方法
通过类型检查判断对象是否是DerivedClass<>的泛型实例,再用反射构造并调用目标泛型方法。
代码实现
public async Task<bool> SetParametersAsync(BaseClass myObject) { if (myObject is MyClassA a) { a.DoThis(); MethodThatExpectsAMyClassAParameter(a); } // ...其他if判断 else { Type objType = myObject.GetType(); // 判断是否是DerivedClass<>的泛型实例 if (objType.IsGenericType && objType.GetGenericTypeDefinition() == typeof(DerivedClass<>)) { // 调用MethodFromGenericClass(如果是公开方法) objType.GetMethod(nameof(DerivedClass<int>.MethodFromGenericClass))?.Invoke(myObject, null); // 获取并调用泛型方法MethodThatExpectsDerivedClassTParameter var targetMethod = typeof(ExampleClass) .GetMethod(nameof(MethodThatExpectsDerivedClassTParameter), BindingFlags.NonPublic | BindingFlags.Instance); var genericMethod = targetMethod?.MakeGenericMethod(objType.GetGenericArguments()[0]); genericMethod?.Invoke(this, new[] { myObject }); } } }
方案3:利用dynamic类型
使用dynamic绕过编译时类型检查,让运行时自动解析泛型类型,这种方式代码更简洁,但会损失编译时类型检查,且有轻微的运行时开销。
代码实现
public async Task<bool> SetParametersAsync(BaseClass myObject) { if (myObject is MyClassA a) { a.DoThis(); MethodThatExpectsAMyClassAParameter(a); } // ...其他if判断 else { Type objType = myObject.GetType(); if (objType.IsGenericType && objType.GetGenericTypeDefinition() == typeof(DerivedClass<>)) { dynamic derived = myObject; derived.MethodFromGenericClass(); // 运行时会自动匹配对应的泛型方法 MethodThatExpectsDerivedClassTParameter(derived); } } }
内容的提问来源于stack exchange,提问作者sth_Weird
相关产品推荐
相关产品推荐

