能否获取或设置私有字段?
我想获取System.Guid.c
。是否有方法可以访问它,还是应该将代码从结构中复制并将字段设置为公共的?
你可以像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);
您可以编写一个扩展方法来获取任何类型的任何私有字段:
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");
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
}
}
}
虽然可以使用反射来实现此操作,但从System.Guid.ToByteArray()
中检索c
可能更容易。
byte[] guid = guid.ToByteArray();
short c = (short)((guid[7] << 8) | guid[6]);
由于这种方法使用公共和文档化的方法,因此它在版本之间变化较少。 (一般来说,应避免依赖私有实现细节,因为这些细节可能会随着版本的更改而发生变化。)