Подтвердить что ты не робот

Доступ к закрытым полям

Можно ли получить или установить частные поля?

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

4b9b3361

Ответ 1

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

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

Ответ 2

Вам следует попробовать 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
        }
    }
}

Ответ 3

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

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

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

Ответ 4

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

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