通过相同对象实例(或基础)的反射调用私有/受保护的方法

时间:2012-01-05 14:43:54

标签: c# vb.net reflection

是否可以通过反射调用受保护的方法。我正在使用这个:

 Me.GetType.InvokeMember(Stages(CurrentStage), 
                         Reflection.BindingFlags.InvokeMethod, 
                         Nothing, 
                         Me, 
                         Nothing)

总是调用没有参数或返回的方法。我的想法是我的对象的用户(业务逻辑的事务处理)继承基类添加一个私有方法来加载。然后,他们按照他们希望触发的顺序将这些方法名称添加到列表中,上面的代码将负责解雇它们。

它适用于公共方法,但不适用于同一个类中的私有或受保护方法(受保护,因为我有一些'标准'预构建方法要添加到基类)。实际上,我可以将这些方法公之于众,但我内心的书呆子不允许我这样做......

我假设这是一个安全功能。有没有办法解决这个问题,或者有没有人对如何继续进行任何建议,但保持我美味,美味的能见度调节剂?

(注意:在VB.NET中使用ITS但如果你觉得这是一个C#答案就好了。)

3 个答案:

答案 0 :(得分:13)

如果要在实例化对象上调用方法,则还需要BindingFlags.Instance。所以代码看起来像(注意:我还添加了BindingFlags选项以在搜索中包含公共成员):

Me.GetType.InvokeMember(Stages(CurrentStage), 
                        BindingFlags.InvokeMethod Or BindingFlags.NonPublic Or BindingFlags.Public Or BindingFlags.Instance, 
                        Nothing, 
                        Me, 
                        Nothing)

有关如何使用此功能的更多信息,请参阅MSDN Documentation

修改

为了支持这个答案,我编写了一个测试程序,演示了publicprotectedprivate类方法的调用。我已将所有课程上传到PasteBin。组成C#控制台应用程序有三个类,因此可以添加到Visual Studio解决方案并运行以进行测试。

  • Program.cs - 设置要调用的方法(包含在SomeClass类中)。执行调用并打印结果。
  • SomeClass.cs - 包含每个可见性修饰符的三种方法:publicprotectedprivate。还注册了自己和Invoker类调用的三个包含方法。
  • Invoker.cs - 接受要调用的类型和方法的注册。然后枚举已注册的类型并调用方法,构建可枚举的结果集合。

随意查看该代码,看看您是否可以找到与您接近它的方式有任何差异。我很欣赏它可能不是最简单的方法。如果您对此有任何疑问,请与我们联系。

答案 1 :(得分:5)

你可能不需要反思。也许我误解了你想要实现的目标,但听起来你想要将一堆方法注入另一种方法,有点包装它们。您可以将私有方法作为委托参数传递。像这样:

public class Base
{
    protected virtual void Execute(IList<Action> actions = null)
    {
        actions = actions ?? new List<Action>();

        // do stuff like begin tran

        foreach (var action in actions)
        {
            action();
        }

        // do stuff like end tran 
    }
}

public class Sub : Base
{
    protected override void Execute(IList<Action> actions = null)
    {
        actions = actions ?? new List<Action>();
        actions.Add(A);
        actions.Add(B);
        base.Execute(actions);
    }

    private void A()
    {
    }

    private void B()
    {
    }
}

Sub的Execute将调用您在Base中编写的代码,然后它将执行A然后执行B,最后执行您在Base中为每个执行的所有内容。

答案 2 :(得分:2)

使用BindingFlags中的NonPublic成员添加您班级中的所有方法:

Me.GetType.InvokeMember(Stages(CurrentStage), 
                         BindingFlags.InvokeMethod Or BindingFlags.NonPublic, 
                         Nothing, 
                         Me, 
                         Nothing)