c# - 调用对象实际类型的公共(public)方法

标签 c# dynamic reflection

考虑以下代码

using System.Reflection;
public class Sample { 
    private class User { 
        public string Name; 
    } 
    private List<User> Users = new List<User> { 
        new User() { Name = "Alice" }, 
        new User() { Name = "Bob" } 
    }; 
}
var sample = new Sample();
var usersOfSample = typeof(Sample).GetField("Users", BindingFlags.Instance | 
    BindingFlags.NonPublic).GetValue(sample);

通过反射,我可以获得 Users 的值,而它是一个 private 类的列表。现在我想对用户调用 List.Clear()。
我的第一个想法是将其转换为动态。但是,以下代码并不像我预期的那样工作。

dynamic usersOfSampleDyn = (usersOfSample as dynamic);
usersOfSampleDyn.Clear();

它抛出一个 RuntimeBinderException。

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'Clear'
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0)
at MyCode

稍后我在 C# Interactive 中尝试这段代码,它说

'object' does not contain a definition for 'Clear'
+ System.Dynamic.UpdateDelegates.UpdateAndExecute1<T0, TRet>(System.Runtime.CompilerServices.CallSite, T0)

使用反射调用这个方法是可行的,如下

usersOfSample.GetType().GetMethod("Clear").Invoke(usersOfSample, new object[0]);

这是我的问题:
1. 将usersOfSample转换为动态时为什么不能调用Clear()?
1.1 在运行时,usersOfSampleDyn 是否解析为 List<T>object { List<T> } ?
1.2 如果 usersOfSampleDyn 被解析为 object { List<T> } , 如何将其转换为 List<T>或者我可以调用Clear()的任何东西在吗?
注:T是私有(private)的。
2. 在 object { List<InaccessibleClass> } 上调用公共(public) List 方法的正确方法是什么? ?

最佳答案

  1. Why I can't call Clear() when cast usersOfSample into dynamic?

因为

1.1 During runtime, is usersOfSampleDyn resolved as a List<T> or a object { List<T> }?

object {List<T>} .

编辑:

The reason dynamic treats the object as object is that dynamic will be treated as the most derived type that is accessible to where it is called.

Jon Hanna's comment 中所述.

1.2 If usersOfSampleDyn was resolved as a object { List<T> }, how to convert it into List or anything I can call Clear() on?

List<T>实现非泛型 IList ,简单地转换为它:

((IList)usersOfSample).Clear();
  1. What's the correct way to call a public List method on object { List<InaccessibleClass> }?

你不知道。如果类(class)无法访问,那么这样做是有原因的。如果是您自己的代码,请更改对象可见性,否则不要在外部代码的内部状态中乱搞,它可能会在任何时候中断并产生意想不到且难以调试的副作用。

但如果您真的需要它,可以反射或转换为 IList。

关于c# - 调用对象实际类型的公共(public)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51532079/

相关文章:

java - Class.getDeclaredMethods 对于没有参数和 void 返回类型的类方法抛出 NoClassDefFoundError

c# - 使用 C# 创建计划任务(任务计划程序托管包装器)

c# - 更新依赖包时强制更新包版本

C# Json 动态对象

c# - 使用左列标题创建动态表的最佳方法

Java反射,改变父类(super class)中声明的字段的值

c# - 将 int[] 连接到相同大小的 string[]

c# - 将 ASP.NET Identity 实现到现有数据库中

Python argparse,根据父参数值提供不同的参数

c# - 为什么参数化通用接口(interface)的 GetMethods() 返回非参数化 MethodInfo