求助:无泛型参数下通过反射实现类型转换,解决Wrapper<T>实例化时内部类型为Object的问题
解决Wrapper类型转换的反射实现问题
我明白你的问题所在了——问题出在泛型方法的类型推断上。当你调用typedValue.BuildWrapper(...)时,typedValue的编译时类型是object,所以C#编译器会自动把BuildWrapper<T>的T推断为object,哪怕它的运行时类型是Placeholder。这就是为什么你得到的是Wrapper<Object>而不是预期的Wrapper<Placeholder>。
要解决这个问题,你需要通过反射显式调用泛型版本的BuildWrapper方法,而不是依赖编译器的类型推断。下面是修改后的ToWrapper扩展方法:
public static class HelperExtensions { public static T CastTo<T>(this object o) => (T)o; public static List<Wrapper> ToWrapper(this IEnumerable<Helper> helperList) { List<Wrapper> wrapperResponseList = new List<Wrapper>(); // 获取BuildWrapper泛型方法的MethodInfo var buildWrapperMethod = typeof(HelperExtensions) .GetMethod(nameof(BuildWrapper), BindingFlags.Static | BindingFlags.Public); foreach (var help in helperList) { if (buildWrapperMethod == null) continue; // 创建对应实际类型的泛型方法版本 var genericBuildWrapper = buildWrapperMethod.MakeGenericMethod(help.Type); // 调用泛型方法:第一个参数是扩展方法的实例对象,后面是foo和bar参数 var wrapper = genericBuildWrapper.Invoke( null, new object[] { help.Obj, Guid.NewGuid(), Guid.NewGuid() } ) as Wrapper; if (wrapper != null) { wrapperResponseList.Add(wrapper); } } return wrapperResponseList; } // 单独调用此方法可正常工作 public static Wrapper<T> BuildWrapper<T>(this T obj, Guid foo, Guid bar) { InnerWrapper<T> inner = new InnerWrapper<T>(obj, bar); return new Wrapper<T>(foo, inner); } }
关键修改点说明:
- 获取
BuildWrapper的MethodInfo:因为BuildWrapper是静态扩展方法,所以从HelperExtensions类中获取它的方法信息。 - 创建泛型方法实例:用
MakeGenericMethod传入help.Type,生成对应实际类型的BuildWrapper<T>方法。 - 调用泛型方法:扩展方法的本质是静态方法,第一个参数就是要扩展的实例对象(这里是
help.Obj),后面跟着foo和bar的Guid参数。 - 类型转换:将调用结果转换为
Wrapper基类,添加到列表中。
测试验证
运行你的测试代码后,你会发现生成的Wrapper实例实际类型是Wrapper<Placeholder>,而非Wrapper<Object>。你可以通过下面的代码验证:
Placeholder placeholder = new Placeholder(Guid.NewGuid()); Helper helper1 = new Helper(placeholder, placeholder.GetType()); var result = new List<Helper> { helper1 }.ToWrapper(); // 验证类型是否正确 var firstWrapper = result.First(); Console.WriteLine(firstWrapper.GetType().Name); // 输出:Wrapper`1 Console.WriteLine(firstWrapper.GetType().GenericTypeArguments[0].Name); // 输出:Placeholder
这样就能正确生成对应实际类型的Wrapper<T>实例了。
内容的提问来源于stack exchange,提问作者TiGreX
相关产品推荐
相关产品推荐

