2012-06-02 5 views
17

Ist es möglich, private Felder zu erhalten oder setzen?Zugang private Felder

Ich möchte System.Guid.c bekommen. Gibt es eine Möglichkeit, darauf zuzugreifen, oder sollte ich einfach den Code von der Strebe kopieren und die Felder veröffentlichen?

+0

Sein eine private Paste –

+0

es geändert, aber es ist nur irgendwie System.Guid. – godzcheater

+1

möglich Duplikat [Finden Sie einen privaten Bereich mit Reflexion?] (Http://stackoverflow.com/questions/95910/find-a-private-field-with-reflection) –

Antwort

24

Sie können Reflektion verwenden, wie von Quantic Programmierung vorgeschlagen

var guid = Guid.NewGuid(); 
var field= typeof (Guid).GetField("_c", BindingFlags.NonPublic |BindingFlags.GetField | BindingFlags.Instance); 
var value = field.GetValue(guid); 

Obwohl, wenn Sie in Ordnung sind mit dem ersten der GUID auf ein Byte-Array konvertiert wird, könnte ich vorschlagen:

var guid = Guid.NewGuid(); 
var c = BitConverter.ToInt16(guid.ToByteArray(), 6); 

Dieser Ansatz vermeidet Reflexion verwendet wird.

bearbeiten

Sie erwähnen, um der Lage sein, als auch um den Wert einzustellen, können Sie nach wie vor Reflexion zu vermeiden:

var guid = Guid.NewGuid(); 
var guidBytes = guid.ToByteArray(); 

// get value 
var c = BitConverter.ToInt16(guidBytes, 6); 

// set value 
Buffer.BlockCopy(BitConverter.GetBytes(c), 0, guidBytes, 6, sizeof(Int16)); 
var modifiedGuid = new Guid(guidBytes); 
+0

Danke, ich denke, es wird die erste verwenden, es sei denn, es gibt ein Negativ für die Verwendung der Reflexion? – godzcheater

+3

@godzcheater - wie von drf erwähnt, ist die Verwendung von Reflektion für den Zugriff auf private Mitglieder in der Regel eine schlechte Übung. Sie verwenden die Interna einer Klasse, um auf Daten zuzugreifen. Wo immer es möglich ist, sollten Sie immer versuchen, sich an die öffentliche API zu halten. Die Reflektion von privaten Mitgliedern erfordert eine vollständige Vertrauensumgebung und hat das Potenzial zu sprödem Code, da sich die Interna der Klasse im Laufe der Zeit ändern können. –

6

Sie sollten versuchen System.Reflection. Hier ein Beispiel:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 

namespace AccessPrivateField 
{ 
    class foo 
    { 
     public foo(string str) 
     { 
      this.str = str; 
     } 
     private string str; 
     public string Get() 
     { 
      return this.str; 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      foo bar = new foo("hello"); 
      Console.WriteLine(bar.Get()); 
      typeof(foo).GetField("str", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(bar, "changed"); 
      Console.WriteLine(bar.Get()); 
      //output: 
      //hello 
      //changed 
     } 
    } 
} 
+1

Es genügt zu bemerken, dass, wenn Sie laufen Silverlight, Sie kann nicht auf die privaten Mitglieder zugreifen. Du hast nicht angegeben, dass du es warst, aber nur für den Fall. –

+0

Warum nicht? Meinst du, du kannst nicht auf die internen Daten von Silverlight zugreifen, oder du kannst es gar nicht tun, wenn du unter Silverlight bist? –

+2

Mit Silverlight verhindert die Laufzeitumgebung den Zugriff auf nicht öffentliche Daten durch Reflektion, da dies ein Sicherheitsproblem darstellt. Zum Beispiel befindet sich ein Teil des Datei-E/A-Codes in der Laufzeit, aber Sie können normalerweise nur auf spezielle, verwaltete Mittel zugreifen, die keine Sicherheitsbedenken verletzen. Wenn Sie Reflexion nutzen könnten, um die Feinheiten der versteckten Datei runter I/O, dann nur auf eine bösartige Silverlight Seite Surfen könnte Wisch-/Ihre Computer-Dateien nach Belieben lesen. –

3

Während es möglich ist, dies mit Reflexion zu tun, kann es einfacher sein um einfach c von System.Guid.ToByteArray() abzurufen.

byte[] guid = guid.ToByteArray(); 
short c = (short)((guid[7] << 8) | guid[6]); 

Da dieser Ansatz öffentliche und dokumentierte Methoden verwendet, unterliegt er weniger Änderungen zwischen den Versionen. (In der Regel sollte auf privaten Implementierungsdetails unter Berufung vermieden werden, da diese Details von Version zu Version ändern können.)

+0

Danke Mann, aber ich muss in der Lage sein, den Wert auch einzustellen. – godzcheater

1

Sie können eine Erweiterungsmethode haben keinen privaten Bereich jeglicher Art zu erhalten:

public static T GetFieldValue<T>(this object obj, string name) { 
    var field = obj.GetType().GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
    return (T)field?.GetValue(obj); 
} 

und dann Zugriff auf ein privates Feld eines beliebigen Typs:

Guid id = Guid.NewGuid(); 
Int16 c = id.GetFieldValue<Int16>("_c");