Можно ли установить частные поля?Доступ к закрытым полям
Я хочу получить System.Guid.c
. Есть ли способ получить к нему доступ, или я должен просто скопировать код из стойки и сделать поля общедоступными?
Можно ли установить частные поля?Доступ к закрытым полям
Я хочу получить System.Guid.c
. Есть ли способ получить к нему доступ, или я должен просто скопировать код из стойки и сделать поля общедоступными?
Вы можете использовать отражение как предложено 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);
Спасибо, я думаю, что он будет использовать первый, если есть негатив, чтобы использовать отражение? – godzcheater
@godzcheater - как упоминалось drf, используя отражение для доступа к частным членам, как правило, является плохой практикой. Вы используете внутренние функции класса для доступа к данным. Там, где это возможно, вы всегда должны стараться придерживаться публичного api. Отражение частных членов потребует полной среды доверия и может быть хрупким кодом, поскольку внутренности класса могут меняться со временем. –
Вы должны попробовать 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
}
}
}
Просто обратите внимание, что если вы используете Silverlight, вы не смогут получить доступ к частным членам. Вы не указали, что были, но на всякий случай. –
Почему бы и нет? Вы имеете в виду, что вы не можете получить доступ к внутренним данным Silverlight, или вы не можете сделать это вообще, когда в Silverlight? –
С Silverlight среда выполнения предотвращает доступ к непубличным данным посредством отражения, поскольку это проблема безопасности. Например, некоторые из файлов ввода/вывода кода находятся во время выполнения, но вы можете получить доступ к нему только с помощью специальных управляемых средств, которые не нарушают требований безопасности. Если бы вы могли использовать рефлексию, чтобы перейти к жесткому скрытому файловому вводу-выводу, то при простом просмотре на злоумышленную страницу Silverlight можно было бы почистить/прочитать файлы ваших компьютеров по своему усмотрению. –
Хотя это можно сделать это с отражением, может быть проще просто получить c
от System.Guid.ToByteArray()
.
byte[] guid = guid.ToByteArray();
short c = (short)((guid[7] << 8) | guid[6]);
Поскольку этот подход использует общедоступные и документированные методы, он менее подвержен изменениям между версиями. (В целом, опираясь на частные детали реализации, следует избегать, так как эти детали могут меняться от версии к версии.)
Спасибо, человек, но мне нужно также установить значение. – godzcheater
Вы можете иметь метод расширения, чтобы получить любое частное поле любого типа:
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");
его частная паста –
Измененным, но его просто System.Guid в любом случае. – godzcheater
Возможный дубликат [Найти личное поле с Reflection?] (Http://stackoverflow.com/questions/95910/find-a-private-field-with-reflection) –