访问私有字段

本文关键字:字段 访问 | 更新日期: 2023-09-27 18:36:01

是否可以获取或设置私有字段?

我想得到System.Guid.c.有没有办法访问它,或者我应该从支柱中复制代码并公开字段?

访问私有字段

您可以按照量化编程的建议使用反射

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

你应该试试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
        }
    }
}

你可以有一个扩展方法来获取任何类型的任何私有字段:

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.ToByteArray()中检索c可能更容易。

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

由于此方法使用公共和记录的方法,因此版本之间不太可能发生更改。 (通常,应避免依赖私有实现详细信息,因为这些详细信息可能会因版本而异。