问题 使用反射访问对象中的Struct的字段


我正在尝试使用反射(最终在编译时未知) 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不能重新定义为原语”。

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


12329
2017-11-09 12:22


起源

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


答案:


坦率地说,没有必要 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);

然而!我会告诉你一些事情:

  • 公共领域而不是属性通常不是一个好主意;这经常会让你迟到
  • 可变结构(即在创建后可以改变的结构)是 几乎从不 一个好主意,并且会更频繁地咬人,并且更难咬
  • 将可变结构和公共领域结合起来可以使它复杂化,但是后来改变也很成问题

16
2017-11-09 12:40



谢谢马克。非常感激。 - Ian Quigley
@Ian只是请注意要点......这不是一个好主意 - Marc Gravell♦
@MarcGravell你可以解释(或给我一个可以学习的链接)为什么在struct上使用反射需要装箱。除了拳击其余的步骤与常规反射相同。 - Sнаđошƒаӽ
@Sнаđошƒаӽ因为所有的反射API都需要 object 作为他们的输入。 - Marc Gravell♦
@Sнаđошƒаӽ它可以 表现 作为一个对象,通过拳击。在那之前:不,它不是“堆”意义上的对象或OO意义上的对象。 - Marc Gravell♦