c# - 反射如何检索分配给变量的数据?

标签 c# reflection

到目前为止,我的理解是,反射用于通过其元数据从程序集中检索类型及其成员的名称。我遇到过一些与以下示例相同的反射示例。

class Person
{
    public string Name {get;set;}
}

static void Main(string[] args)
{
    Person person = new Person();
    person.Name = "John";
    Console.WriteLine(person.GetType().GetProperty("Name").GetValue(person)); //John
    person.Name = "Mary";
    Console.WriteLine(person.GetType().GetProperty("Name").GetValue(person)); //Mary
}

我了解反射如何获取类型、成员等的名称,因为这是存储在程序集元数据中的内容,但是反射如何检索与其关联的值?这是在程序执行期间发生变化的动态数据(如示例所示),程序集的元数据不包含这些数据(对吗?)。

如果您能澄清 Reflection 如何检索实际值以及情况是否确实如此,我们将不胜感激。我说的不对的地方请指正!

最佳答案

简短的回答是反射是运行时的一项功能,因此它可以访问运行时信息。如果它是一个没有运行时“钩子(Hook)”的单独库,那么你是对的,它无法在运行时获取属性值,或进行调用,或任何其他本质上无法从程序集文件中观察到的内容在磁盘上。

长答案,我向自己证明了这一点:

Microsoft 提供了用于编写 .NET Framework 基类库的 C# 源代码的引用版本。如果我们查看您在示例中使用的 PropertyInfo.GetValue(object) 方法,它的定义为 here 。追踪电话线索,我们最终到达 an abstract method of the same name但参数不同。源文件的更下方是实现类 RuntimePropertyInfoits override of GetValue我们看到它是通过调用属性的 get 访问器来实现的(因为,在幕后,属性只是具有某些签名约定的方法的集合 - GetGetMethod 是一个有趣的名字,含义“获取当前属性定义为 get 的方法”):

MethodInfo m = GetGetMethod(true);
if (m == null)
    throw new ArgumentException(System.Environment.GetResourceString("Arg_GetMethNotFnd"));
return m.Invoke(obj, invokeAttr, binder, index, null); 

如果我们在 MethodInfo.Invoke 上进行类似的探索之旅,我们最终会到达 RuntimeMethodHandle.InvokeMethod ,其声明为:

[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern static object InvokeMethod(object target, object[] arguments, Signature sig, bool constructor);

extern keyword在类上意味着“我在 C# 中没有此方法的主体,请在其他地方查找”。对于大多数 C# 用户来说,这意味着他们正在使用 DllImport引用 native 代码,但此方法有一个不同的属性:MethodImpl ,与 MethodImplOptions.InternalCall枚举值。这是 C# 对编译器说的方式:“我没有主体,但实际运行时本身有”。

因此,在我们的旅程结束时,我们到达了 Reflection API 依赖于运行时本身的地步。当然,运行时和基类库必须同时开发,以确保这些同步点的存在。

有趣的是,.NET 的实际标准 - ECMA-335 - 当实现(意味着运行时 + 基类库)遵守最低限度的“内核配置文件”时,使反射 API 成为可选(引用:第 6 版,第 IV.4.1.3 节)。因此,实际上存在 .NET 的实现,您明确允许像这样检查运行时,但考虑到某些类型的应用程序对反射的依赖,所有大型实现(原始 .NET Framework、 .NET Core/新的 .NET 和 Mono)提供了它。

关于c# - 反射如何检索分配给变量的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70538983/

相关文章:

c# - ASP.NET Imagebutton在ValidationGroup验证后执行jQuery功能

c# - 为什么 .Net 框架类中的静态方法总是线程安全的?

c# - 四舍五入到最接近的以 9 结尾的数字

java - 使用类对象作为类型

reflection - F# 类型提供程序引用自定义类型

c# - 这是观察者反模式吗? (有奖金状态机问题)

c# - WPF MVVM : TextBox needing format and Button with IsDefault set to True

java - 通过反射访问Java中的私有(private)变量

ruby-on-rails - 方法,返回实例方法列表

.net - 从托管 dll 中查找可执行文件名称,com-visible