2012-11-09 5 views
9

Sto tentando di utilizzare la riflessione (ultimamente su sconosciuto al momento della compilazione) object che include struct. Sono arrivato fino al TypedReference.MakeTypedReference ma ho colpito un muro.Campi di accesso di una struttura in un oggetto con riflessione

Ecco la mia classe e Struct

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

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

Ed ecco come lo sto cercando di impostare "Codice" di "Valore" in MyObject utilizzando la riflessione. Come menzionato sopra, sto cercando una soluzione che non conosca questi tipi in fase di compilazione (sarebbe troppo facile!)

Ecco il codice che ho finora (ho usato [0], [1] per rendere il codice più semplice)

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"); 

il TypedReference.MakeTypedReference esplode con; "FieldInfo non corrisponde al tipo di destinazione." Allo stesso modo, se ho appena passato objFields[1]. E se passano solo moneyFields ottengo "Non è possibile ridefinire le TypedReferen come primitive".

Perché? Diciamo che sto creando attrezzature di prova casuali e vogliono compilare i campi di classe con dati casuali :)

+0

Stai dicendo che al momento della compilazione non sai se utilizza MyObject o Money, quindi deve rilevare quale oggetto viene utilizzato e leggere/scrivere la proprietà di conseguenza? – series0ne

+0

Che ne dici di usare AutoFixture e uscire dal mercato delle macchine Rube Goldberg? (Anche se wrt 'struct', vedi http://stackoverflow.com/questions/12930963/creating-a-struct-with-autofixture-throws-no-public-constructor-error) (non hai avuto bisogno di' MakeTypedReference 'professionalmente e devo dire qualcosa come mi è capitato di guardare effettivamente il tweet stream per una volta, sry!) –

+0

@RubenBartelink - il" perché "era semplicemente un riferimento. Avrei sicuramente usato AutoFixture se era quello che stavo facendo. –

risposta

13

Francamente, non c'è bisogno di alcun tipo per TypedReference qui - solo una struttura scatolata dovrebbe funzionare bene:

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); 

Però! Ti consiglierò alcune cose:

  • I campi pubblici invece delle proprietà non sono solitamente una buona idea; che spesso ti morderà più tardi
  • le strutture mutabili (cioè struct che possono essere modificate dopo la creazione) sono quasi mai una buona idea, e morderà ancora più spesso, e mordere duro
  • che unisce le strutture mutevoli e composti campi pubblici ma è molto problematico cambiare in seguito
+1

Grazie Marc. Molto apprezzato. –

+5

@Io solo per favore nota i punti elenco ... questa non è una grande idea –

Problemi correlati