【问题标题】:Access fields of a Struct in an Object with Reflection使用反射访问对象中结构的字段
【发布时间】:2012-11-09 12:22:36
【问题描述】:

我正在尝试使用反射(最终在编译时未知)object,其中包括struct。我已经到了TypedReference.MakeTypedReference,但我碰壁了。

这是我的类和结构

public class MyObject
{
    public int Id;
    public Money Amount; 
}

public struct Money
{
    public int Vaule;
    public string Code;
}

这就是我如何尝试使用反射在 MyObject 中设置“金额”的“代码”。正如我上面提到的,我正在寻找一个在编译时不知道这些类型的解决方案(这太容易了!)

这是我目前的代码(我使用 [0]、[1] 来简化代码)

var obj = new MyObject() { Id = 1 };
obj.Amount.Vaule = 10;
obj.Amount.Code = "ABC";

FieldInfo[] objFields = obj.GetType().GetFields();
FieldInfo[] moneyFields = objFields[1].GetValue(obj).GetType().GetFields();

List<FieldInfo> fields = new List<FieldInfo>() { objFields[1] };
fields.AddRange( moneyFields );

TypedReference typeRef = TypedReference.MakeTypedReference( 
                           objFields[1].GetValue( obj ), fields.ToArray() );

moneyFields[1].SetValueDirect( typeRef, "XXX" );

TypedReference.MakeTypedReference 爆炸了; “FieldInfo 与目标类型不匹配。”同样,如果我只是通过objFields[1]。如果只通过 moneyFields 我得到“TypedReferences 不能被重新定义为原语。”

为什么?假设我正在创建随机测试装置并希望用随机数据填充类字段:)

【问题讨论】:

  • 你是说在编译时你不知道它使用的是MyObject还是Money,所以它需要检测正在使用的对象并相应地读/写属性?
  • 使用 AutoFixture 并摆脱反射式 Rube Goldberg 机器业务怎么样? (虽然 wrt struct,请参阅 stackoverflow.com/questions/12930963/…)(没有遇到任何对 MakeTypedReference 的专业需求,并且不得不说些什么,因为我碰巧实际上正在观看一次推文流,对不起!)
  • @RubenBartelink - “为什么”仅供参考。如果那是我正在做的事情,我会使用 AutoFixture。
  • @activwerx 它纯粹是使用对未知对象和结构的反射。 Marc 在下面的回答是这种情况的完美答案。
  • @IanQuigley 我猜我肯定不想解决真正的问题......

标签: c# reflection typedreference


【解决方案1】:

坦率地说,这里不需要TypedReference - 只是一个盒装结构应该可以正常工作:

    var amountField = obj.GetType().GetField("Amount");
    object money = amountField.GetValue(obj);
    var codeField = money.GetType().GetField("Code");
    codeField.SetValue(money, "XXX");
    amountField.SetValue(obj, money);

但是!我会给你一些建议:

  • 公共字段而不是属性通常不是一个好主意;以后经常会咬你
  • 可变结构(即可以在创建后更改的结构)几乎从来没有是个好主意,而且会更频繁地咬人,咬得更紧
  • 将可变结构和公共字段组合在一起,但以后更改会很麻烦

【讨论】:

  • 谢谢马克。非常感谢。
  • @Ian 请注意要点...这不是一个好主意
  • @MarcGravell 你能否解释一下(或提供一个我可以从中学习的链接)为什么在结构上使用反射需要拳击。除了拳击,其余步骤与常规反射相同。
  • @Sнаđошƒаӽ 因为所有反射 API 都将 object 作为输入。
  • @Sнаđошƒаӽ 它可以通过拳击表现作为一个对象。在那之前:不,它不是“堆”意义或 OO 意义的对象。
猜你喜欢
  • 2020-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
相关资源
最近更新 更多