【问题标题】: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&lt;Wrapper&gt;。请注意,这是一个包装器列表,而不是 wrapper&lt;T&gt; 列表,这意味着 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&lt;Helper&gt; 转换为 List&lt;Wrapper&gt; 并且它做到了,但内部对象是 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&lt;Wrapper&gt;,但它生成的不是wrapper&lt;T&gt;,而是Wrapper&lt;Object&gt;

知道如何正确投射吗?

我还创建了一个小提琴https://dotnetfiddle.net/pz3JDz,其中包含所有需要测试的代码。

提前感谢您的帮助。

【问题讨论】:

  • 你为什么不直接调用 BuildWrapper&lt;T&gt; 作为泛型?类似typeof(HelperExtensions).GetMethod("BuildWrapper").MakeGenericMethod(new[] { help.Type}).Invoke(this,help.Obj)
  • @Franck 我没有想到那个选项;有效。回答问题,以便我给你打绿色勾:D,谢谢。

标签: c# .net .net-core reflection


【解决方案1】:

局部变量typedValuevar声明,因为genericMethodInfo?.Invoke(...)返回object类型的回复,所以该局部变量typedValue的类型将是object。之后在这里调用泛型方法Wrapper&lt;T&gt; BuildWrapper&lt;T&gt;(this T obj, ...),因为typedValue 的类型是objectT 的类型也是object,因此它会返回Wrapper&lt;object&gt;

解决它而不是这个:

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&lt;T&gt; 检索对象的调用。 您可以执行以下操作。您显然可以重新格式化以进行错误检查,但您明白了。

    var wrapperGeneric = typeof(HelperExtensions).GetMethod("BuildWrapper").MakeGenericMethod(new[] { help.Type}).Invoke(this,help.Obj)
    

    【讨论】:

      猜你喜欢
      • 2017-07-25
      • 1970-01-01
      • 1970-01-01
      • 2012-06-25
      • 1970-01-01
      • 2021-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多