2012-06-02 3 views
17

Можно ли установить частные поля?Доступ к закрытым полям

Я хочу получить System.Guid.c. Есть ли способ получить к нему доступ, или я должен просто скопировать код из стойки и сделать поля общедоступными?

+0

его частная паста –

+0

Измененным, но его просто System.Guid в любом случае. – godzcheater

+1

Возможный дубликат [Найти личное поле с Reflection?] (Http://stackoverflow.com/questions/95910/find-a-private-field-with-reflection) –

ответ

24

Вы можете использовать отражение как предложено Quantic Программирование

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

Хотя если все в порядке с первым превращением Guid в массив байтов, я мог бы предложить:

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

Последний подход позволяет избежать отражения.

Редактировать

Вы упоминаете нуждаясь, чтобы иметь возможность установить значение, а также, вы можете избежать отражения:

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

Спасибо, я думаю, что он будет использовать первый, если есть негатив, чтобы использовать отражение? – godzcheater

+3

@godzcheater - как упоминалось drf, используя отражение для доступа к частным членам, как правило, является плохой практикой. Вы используете внутренние функции класса для доступа к данным. Там, где это возможно, вы всегда должны стараться придерживаться публичного api. Отражение частных членов потребует полной среды доверия и может быть хрупким кодом, поскольку внутренности класса могут меняться со временем. –

6

Вы должны попробовать System.Reflection. Вот пример:

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

Просто обратите внимание, что если вы используете Silverlight, вы не смогут получить доступ к частным членам. Вы не указали, что были, но на всякий случай. –

+0

Почему бы и нет? Вы имеете в виду, что вы не можете получить доступ к внутренним данным Silverlight, или вы не можете сделать это вообще, когда в Silverlight? –

+2

С Silverlight среда выполнения предотвращает доступ к непубличным данным посредством отражения, поскольку это проблема безопасности. Например, некоторые из файлов ввода/вывода кода находятся во время выполнения, но вы можете получить доступ к нему только с помощью специальных управляемых средств, которые не нарушают требований безопасности. Если бы вы могли использовать рефлексию, чтобы перейти к жесткому скрытому файловому вводу-выводу, то при простом просмотре на злоумышленную страницу Silverlight можно было бы почистить/прочитать файлы ваших компьютеров по своему усмотрению. –

3

Хотя это можно сделать это с отражением, может быть проще просто получить c от System.Guid.ToByteArray().

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

Поскольку этот подход использует общедоступные и документированные методы, он менее подвержен изменениям между версиями. (В целом, опираясь на частные детали реализации, следует избегать, так как эти детали могут меняться от версии к версии.)

+0

Спасибо, человек, но мне нужно также установить значение. – godzcheater

1

Вы можете иметь метод расширения, чтобы получить любое частное поле любого типа:

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

а затем доступ к закрытому полю произвольного типа:

Guid id = Guid.NewGuid(); 
Int16 c = id.GetFieldValue<Int16>("_c"); 
Смежные вопросы