2013-12-17 9 views
5

Ich habe eine Struktur, die eine Tonne benannte Bool-Mitglieder hat. (Bitte verlassen Sie gute Beispiele und solche, die jetzt wegen des Beispiels nicht berücksichtigt werden).Setzen Sie alle Bool-Elemente eines Objekts mit Reflektion

Ich möchte diese Werte zu Testzwecken nach dem Zufallsprinzip entweder auf wahr oder falsch setzen.

Wie kann ich dies durch Reflexion tun? Diese

ist das, was ich bisher:

 Random r = new Random(); 
     foreach (var bool_field in state.GetType().GetFields().Where(x => x.GetType() == false.GetType())) 
     { 
      bool_field.SetValue(state, r.Next() % 2 == 0 ? true : false); 
     } 

Leider ist es nie die Schleife eintritt.

UPDATE 1:

Hier ist, wie die Systemstate Struktur aussieht, welche die Art des Zustand variabel ist. Es ist mit Bool Auto Eigenschaften gefüllt.

public struct SystemState 
{ 
    ... 
    public bool CanYouHelpMeOnThisOne { get; set; } 
    ... 
} 

UPDATE 2:

Die Lösung unten geschrieben scheint nett, aber es funktioniert nicht. Der Grund dafür ist, dass SystemState eine Struktur und keine Klasse ist. Daher ist es ein Werttyp und kein Referenztyp. Daher hat das Aufrufen der SetValue-Methode keine Auswirkungen. Nach dem Ändern von SystemState in Klasse funktioniert die folgende Lösung einwandfrei.

Jetzt gibt es noch einen anderen Weg, dies zu erreichen, ohne SystemState zu Klasse zu ändern?

+1

@horgh: Vorausgesetzt, er hat einige 'Bool'-Mitglieder in dort. –

+1

Nur eine Randnotiz: Da Sie zur Kompilierzeit wissen, dass Sie 'Boolean' Felder setzen wollen, würde ich' typeof (Boolean) 'anstelle von' false.GetType() 'verwenden. –

Antwort

8

Zuerst müssen Sie die Where Klausel ändern:

x => x.FieldType == false.GetType() 

Da die Art der x ist FieldInfo


Seit der zuletzt die OP es keine Felder gibt, aber Eigenschaften. Also, sollten Sie GetProperties verwenden, um die Liste der Eigenschaften zu erhalten, und vergleichen Sie die PropertyType, als x wäre dann PropertyInfo dann. Auch die SetValue Methode wird die andere Signatur haben.

foreach (var bool_field in state.GetType() 
           .GetProperties() 
           .Where(x => x.PropertyType == false.GetType())) 
{ 
    bool_field.SetValue(state, r.Next() % 2 == 0 ? true : false, null); 
} 

Basierend auf OP Kommentare, wenn Sie die Unterstützung Felder zugreifen möchten, können Sie den folgenden Code verwenden:

var fs = state.GetType() 
       .GetFields(BindingFlags.Instance | BindingFlags.NonPublic) 
       .Where(x => x.FieldType == typeof(bool)); 
foreach (var f in fs) 
{ 
    f.SetValue(state, true); 
} 

Die Überlastung von GetFields ohne Argumente gibt alle öffentlichen Felder des aktuellen Typs. Während in Ihrem Fall benötigen Sie die private diejenigen, so verwenden Sie die Type.GetFields Method (BindingFlags) mit der geeigneten BindingFlags.

+0

Soweit ich auf Assembly-Ebene weiß, gibt es für jede Auto-Eigenschaft ein Backing-Feld. Werden sie nicht von der GetFields() - Methode des Typs ausgewählt? – VSZM

+0

Sie können es leicht selbst mit Ihrem aktuellen Code überprüfen ....Denken Sie daran, 'x.GetType()' in 'x.FieldType' zu ​​ändern. – horgh

+0

Außerdem scheint es überhaupt nicht gut zu sein, direkt mit den Backing-Feldern zu arbeiten. – horgh

Verwandte Themen