2012-06-02 5 views
17

Czy można uzyskać lub ustawić prywatne pola?Dostęp do pól prywatnych

Chcę uzyskać System.Guid.c. Czy jest jakiś sposób, aby uzyskać do niego dostęp, czy powinienem skopiować kod z kolumny i uczynić pola publicznymi?

+0

jego prywatny pasta –

+0

zmienił go, ale jej po prostu System.Guid tak. – godzcheater

+1

możliwy duplikat [Znajdź prywatne pole z Refleksją?] (Http://stackoverflow.com/questions/95910/find-a-private-field-with-reflection) –

Odpowiedz

24

Można użyć refleksji sugerowane przez Quantic Programowanie

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

Chociaż, jeśli są w porządku z przekształcając najpierw GUID do tablicy bajtów, mogę zasugerować:

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

To ostatnie podejście unika używania refleksji.

Edit

wspomniałeś potrzeby móc ustawić wartość, jak dobrze, można jeszcze uniknąć refleksji:

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

Dziękuję, myślę, że będzie to pierwsze, chyba że jest negatyw do korzystania z refleksji? – godzcheater

+3

@godzcheater - jak wspomina drf, używanie refleksji w celu uzyskania dostępu do prywatnych członków jest ogólnie złą praktyką. Używasz elementów wewnętrznych klasy, aby uzyskać dostęp do danych. Tam gdzie to możliwe, zawsze powinieneś próbować trzymać się publicznej api. Odbicie prywatnych członków będzie wymagało pełnego środowiska zaufania i może być kruchym kodem, ponieważ wewnętrzne elementy klasy mogą się zmieniać z czasem. –

6

Powinieneś spróbować System.Reflection. Oto przykład:

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

Po prostu zauważ, że jeśli używasz Silverlight, możesz nie będzie mógł uzyskać dostępu do prywatnych członków. Nie sprecyzowałeś, że jesteś, ale na wszelki wypadek. –

+0

Dlaczego nie? Czy masz na myśli, że nie możesz uzyskać dostępu do wewnętrznych danych Silverlight, lub nie możesz tego zrobić w ogóle w Silverlight? –

+2

Dzięki oprogramowaniu Silverlight środowisko wykonawcze uniemożliwia dostęp do danych niepublicznych poprzez odbicie, ponieważ jest to problem związany z bezpieczeństwem. Na przykład niektóre pliki we/wy pliku znajdują się w środowisku wykonawczym, ale zazwyczaj można uzyskać do nich dostęp tylko za pomocą specjalnych, zarządzanych środków, które nie naruszają zabezpieczeń. Jeśli mógłbyś użyć refleksji, aby dostać się do ukrytego pliku I/O, to po prostu przeglądając złośliwą stronę Silverlight możesz czyścić/czytać pliki komputerów do woli. –

3

ile to możliwe, aby zrobić to z refleksji, może być łatwiej po prostu pobrać c z System.Guid.ToByteArray().

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

Ponieważ to podejście wykorzystuje publiczne i udokumentowane metody, mniej podlega zmianom między wersjami. (W ogóle, opierając się na prywatnych szczegółów implementacji powinny być unikane, ponieważ dane te mogą ulec zmianie z wersji na wersję.)

+0

Dzięki człowieku, ale muszę też móc ustawić wartość. – godzcheater

1

Można mieć metodę rozszerzenia, aby uzyskać jakiekolwiek prywatne pole dowolnego typu:

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

a następnie uzyskać dostęp do prywatnych pola z dowolnego typu:

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