访问私有字段

god*_*ter 18 .net c# private

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

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

Chr*_*ter 28

您可以使用Quantic Programming建议的反射

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

虽然如果你可以将guid转换为字节数组,我可能会建议:

var guid = Guid.NewGuid();
var c = BitConverter.ToInt16(guid.ToByteArray(), 6);
Run Code Online (Sandbox Code Playgroud)

后一种方法避免使用反射.

编辑

你提到需要能够设置值,你仍然可以避免反射:

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);
Run Code Online (Sandbox Code Playgroud)

  • @godzcheater - 正如drf所提到的,使用反射访问私有成员通常是不好的做法.您正在使用类的内部来访问数据.在可能的情况下,你应该总是试着坚持公众api.私人成员的反思将需要一个完整的信任环境,并且有可能成为脆弱的代码,因为班级内部可能会随着时间的推移而发生变化. (3认同)

Mar*_*gal 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 使用Silverlight,运行时会阻止您通过反射访问非公共数据,因为这是一个安全问题.例如,某些文件I/O代码位于运行时,但通常只能通过特殊的托管方式访问它,而不会违反安全问题.如果您可以使用反射来深入了解隐藏文件I/O的细节,那么只需浏览恶意Silverlight页面就可以随意擦除/读取您的计算机文件. (2认同)

Bru*_*ell 6

您可以使用扩展方法来获取任何类型的任何私有字段:

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);
}
Run Code Online (Sandbox Code Playgroud)

然后访问任意类型的私有字段:

Guid id = Guid.NewGuid();
Int16 c = id.GetFieldValue<Int16>("_c");
Run Code Online (Sandbox Code Playgroud)