没有泛型参数的反射转换为类型
Posted
技术标签:
【中文标题】没有泛型参数的反射转换为类型【英文标题】:Cast to Type with reflection without generic argument 【发布时间】:2021-07-05 12:36:43 【问题描述】:我有一个涉及转换为不同类型的问题
我有一个包装器类,它包含一个内部包装器,其中包含T
这是结构:
public class Wrapper
public readonly Guid Foo;
public Wrapper(Guid foo)
Foo = foo;
public class Wrapper<T> : Wrapper
public readonly InnerWrapper<T> InnerWrapper;
public Wrapper(Guid foo, InnerWrapper<T> innerWrapper)
: base(foo)
InnerWrapper = innerWrapper;
public class InnerWrapper<T>
public readonly Guid Bar;
public readonly T Content;
public InnerWrapper(T content, Guid bar)
Content = content;
Bar = bar;
在代码的另一部分我有一个List<Wrapper>
。请注意,这是一个包装器列表,而不是 wrapper<T>
列表,这意味着 T 可以是任何类。
当这个翻译预计会有类似的东西
wrapper<Class1>,
wrapper<Class2>
等等。
在代码中的某个位置有一个“帮助类”,其中包含object
类型的对象和Type
public class Helper
public readonly object Obj;
public readonly Type Type;
public Helper(object obj, Type type)
Obj = obj;
Type = type;
这就是我的问题开始的地方,我创建了一个辅助方法来从 List<Helper>
转换为 List<Wrapper>
并且它做到了,但内部对象是 object
类型而不是实际类型。
而且我不知道如何在不使用泛型的情况下将 object
转换为实际类型,并且由于 T 可以是多个类型,我无法使用它们。
这是辅助类
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>();
foreach (var help in helperList)
// doesn't work either var typedValue = Convert.ChangeType(help.Obj, help.Type);
var methodInfo = typeof(HelperExtensions).GetMethod(nameof(CastTo), BindingFlags.Static | BindingFlags.Public);
var genericArguments = new[] help.Type ;
var genericMethodInfo = methodInfo?.MakeGenericMethod(genericArguments);
var typedValue = genericMethodInfo?.Invoke(null, new[] help.Obj );
var wrapper = typedValue.BuildWrapper(Guid.NewGuid(), Guid.NewGuid());
wrapperResponseList.Add(wrapper);
return wrapperResponseList;
//This one called individually does the work properly
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);
为了在这里显示代码,我还创建了一个测试类
public class Placeholder
public Guid Value get;
public Placeholder(Guid value)
Value = value;
所以当我打电话时
Placeholder placeholder = new Placeholder(Guid.NewGuid());
Helper helper1 = new Helper(placeholder, placeholder.GetType());
var result = new List<Helper> helper1 .ToWrapper();
它生成一个List<Wrapper>
,但它生成的不是wrapper<T>
,而是Wrapper<Object>
知道如何正确投射吗?
我还创建了一个小提琴https://dotnetfiddle.net/pz3JDz,其中包含所有需要测试的代码。
提前感谢您的帮助。
【问题讨论】:
你为什么不直接调用BuildWrapper<T>
作为泛型?类似typeof(HelperExtensions).GetMethod("BuildWrapper").MakeGenericMethod(new[] help.Type).Invoke(this,help.Obj)
@Franck 我没有想到那个选项;有效。回答问题,以便我给你打绿色勾:D,谢谢。
【参考方案1】:
局部变量typedValue
用var
声明,因为genericMethodInfo?.Invoke(...)
返回object
类型的回复,所以该局部变量typedValue
的类型将是object
。之后在这里调用泛型方法Wrapper<T> BuildWrapper<T>(this T obj, ...)
,因为typedValue
的类型是object
,T
的类型也是object
,因此它会返回Wrapper<object>
。
解决它而不是这个:
var wrapper = typedValue.BuildWrapper(Guid.NewGuid(), Guid.NewGuid());
这样做:
var buildWrapperMethodInfo = typeof(HelperExtensions).GetMethod(nameof(BuildWrapper), BindingFlags.Static | BindingFlags.Public);
var buildWrapperGenericMethodInfo = buildWrapperMethodInfo?.MakeGenericMethod(genericArguments);
var wrapper = buildWrapperGenericMethodInfo?.Invoke(null, new[] typedValue, Guid.NewGuid(), Guid.NewGuid() );
然后在此处添加类型转换:
wrapperResponseList.Add((Wrapper)wrapper);
【讨论】:
【参考方案2】:可以简化直接从BuildWrapper<T>
检索对象的调用。
您可以执行以下操作。您显然可以重新格式化以进行错误检查,但您明白了。
var wrapperGeneric = typeof(HelperExtensions).GetMethod("BuildWrapper").MakeGenericMethod(new[] help.Type).Invoke(this,help.Obj)
【讨论】:
以上是关于没有泛型参数的反射转换为类型的主要内容,如果未能解决你的问题,请参考以下文章