【问题标题】:Reflection: casting reflected type to generic with type as string and iterating over it反射:将反射类型转换为泛型,类型为字符串并对其进行迭代
【发布时间】:2015-02-27 05:46:29
【问题描述】:

我搜索了 StackOverflow 并发现了多个相关问题,但没有一个可以“完全”回答它。我的理解可能有误,但想检查一下 -

我有课

public class Foo
{
     public List<Bar> Bars = new List<Bar>();
}

public class Bar
{
}

由于发生了一些疯狂的反射,此列表仅作为对象传递 -

Foo f = new Foo();
object o = f;
CheckItem(o, "Bars");

// CheckItem has no clue about Bar class and is thus passed the 'Bars' Field name 
public void CheckItem(Object obj, string fieldName)
{
    var value = obj.GetType().GetField(fieldName).GetValue(obj); // returns f.Bars into value as object

    foreach (var bar in value.Bars) // won't compile as value is type object
}

所以,我使用 MakeGenericType 和 Activator.CreateInstance 魔法

var genericClass = typeof(List<>).MakeGenericType(new[] {value.GetType().FieldType.GetGenericArguments()[0]}); // makes a generic of type List<Bar>
var o = Activator.CreateInstance(genericClass); // o is again of type object
foreach (var bar in o.Bars) // will fail again

SO - 我如何调用 foreach 循环来迭代成员。我在 MakeGenericType 周围看到的每个示例都以创建对象 o 结束,没有人谈论如何访问其成员,尤其是在上面的 foreach 循环中。

感谢任何输入。

谢谢

【问题讨论】:

  • 不清楚你为什么要使用CreateInstance - 你不想创建一个 new 实例,对吧?您只想迭代 现有的
  • @JonSkeet:是的,我只需要遍历新实例。我使用 CreateInstance 作为最后的手段,只是提到我也尝试过这种方法,尽管我知道它不是必需的。
  • 您应该能够转换为IEnumerable(而不是IEnumerable&lt;T&gt;)并对其进行迭代。
  • @MattBurland:是的,没有意识到这一点。谢谢!

标签: c# .net generics reflection


【解决方案1】:

如果您不需要知道元素类型,您只需将其转换为IEnumerable

var sequence = (IEnumerable) value;
foreach (var item in sequence)
{
    // The type of the item variable is just object,
    // but each value will be a reference to a Bar
}

(顺便说一句,我强烈建议使用私有字段并公开属性 - 但这是另一回事。)

【讨论】:

  • 混蛋!没有意识到我只能投射到 IEnumeratble !多哈。谢谢!
  • GetValue 返回object 您需要将其转换为诸如IEnumerable 之类的内容。请记住,演员阵容可能会引发异常,因此请为这种可能性做好准备。
猜你喜欢
  • 2021-07-05
  • 1970-01-01
  • 2018-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
相关资源
最近更新 更多