2012-11-09 57 views
9

我試圖使用反射(最終在編譯時未知)object其中包括struct。我得到了儘可能多的TypedReference.MakeTypedReference,但我碰到了一堵牆。使用反射訪問對象中Struct的字段

這裏是我的class和struct

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不能被重新定義爲原語。」

爲什麼?比方說,我創建隨機測試夾具和要填充類字段用隨機數據:)

+0

你是說在編譯時你不知道它是否使用MyObject或Money,所以它需要檢測哪個對象正在使用和讀/寫屬性因此? – series0ne

+0

如何使用AutoFixture並退出反射Rube Goldberg機器業務? (雖然wrt'struct',請參閱http://stackoverflow.com/questions/12930963/creating-a-struct-with-autofixture-throws-no-public-constructor-error)(沒有遇到任何需要'MakeTypedReference '專業,不得不說,因爲我碰巧實際上正在看tweet流一次,謝謝!) –

+0

@RubenBartelink - 「爲什麼」只是供參考。如果那是我正在做的事,defo會使用AutoFixture。 –

回答

13

坦率地說,沒有必要不對因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); 

然而!我會告訴你幾件事情:

  • 公用字段而不是屬性通常不是一個好主意;這往往會咬你以後
  • 可變結構(可創建之後不得更改,即結構)是幾乎從未一個好主意,會咬人,甚至更多的時候,咬較硬
  • 結合可變結構和公共領域的化合物它,但使它成爲以後很難
+1

謝謝馬克。非常感激。 –

+5

@Ian只是請注意項目符號...這不是一個好主意 –