15

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

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

4

1 回答 1

19

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

然而!我会给你一些建议:

  • 公共字段而不是属性通常不是一个好主意;以后经常会咬你
  • 可变结构(即可以在创建后更改的结构)几乎从来都不是一个好主意,而且会更频繁地咬,咬得更紧
  • 将可变结构和公共字段组合起来,使其变得更加复杂,但是以后更改会很成问题
于 2012-11-09T12:40:34.303 回答