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

发布于 2024-12-24 19:04:19 字数 593 浏览 1 评论 0原文

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

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

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

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

我假设这是一个安全功能。有没有办法解决这个问题,或者有人对如何继续但保持我的美味可见性修改器完好无损有任何建议吗?

(注意:它在 VB.NET 中,但如果您愿意的话,C# 答案也可以)。

Is it possible to call a protected method via reflection. I am using this:

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

Which always calls a method with no params or return. The idea is that the user of my object (transactional processing of business logic) inherits the base class adds in a load of private methods to fire. They then add these method names to a list in the order they would like them fired and the code above will take care of firing them.

It works fine with public methods but not with private or protected methods in the same class (Protected because I have some 'standard' pre built methods to add to the base class). Realistically I could make the methods public and be done with it but my inner nerd wont allow me to do so...

I am assuming this is a security feature. Is there a way to get around this or does anyone have any suggestions on how to proceed but keep my tasty, tasty visibility modifiers in tact?

(NOTE: ITS IN VB.NET but a C# Answer is fine if that is what you are comfortable with).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

恋你朝朝暮暮 2024-12-31 19:04:19

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

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

有关如何使用此选项的更多信息,请参阅 MSDN 文档

编辑

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

  • Program.cs - 设置要调用的方法(包含在 SomeClass 类)。执行调用并打印结果。
  • SomeClass.cs - 包含每个可见性修饰符的三个方法: public受保护私有。还注册其自身以及三个包含的方法以供 Invoker 类调用。
  • Invoker.cs - 接受要调用的类型和方法的注册。然后枚举已注册的类型并调用方法,构建可枚举的结果集合。

请随意查看该代码,看看您是否可以发现处理方式上的任何差异。不过,我知道这可能不是最简单的方法。如果您对此还有任何疑问,请告诉我。

If you are invoking the methods on an instantiated object, you will also need BindingFlags.Instance. So the code would look like (Note: I've also added the BindingFlags option to include public members in the search):

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

For more information on how to use this, refer to the MSDN Documentation.

EDIT

To support this answer, I have written a test program that demonstrates the invocation of public, protected and private class methods. I have uploaded all classes to PasteBin. There are three classes that make up a C# Console Application, so can be added to a Visual Studio solution and run to test.

  • Program.cs - Sets up the methods to be invoked (contained within the SomeClass class). Executes the invocation and prints the results.
  • SomeClass.cs - Contains three methods of each of the visibility modifiers: public, protected and private. Also registers itself and the three contained methods for invocation by the Invoker class.
  • Invoker.cs - Accepts registration of types and methods that are to be invoked. Then enumerates the registered types and invokes the methods, building an enumerable collection of results.

Feel free to look over that code and see if you can find any differences in how you are approaching it. I appreciate it may not be the simplest of approaches, though. Let me know if you have any further queries on it.

月依秋水 2024-12-31 19:04:19

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

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 中的 foreach 之后声明的所有内容。

You might not need reflection for this. Maybe I misunderstood what you wanted to achieve but it sounds like you want to inject a bunch of methods to another method, kinda wrap them. You can pass in the private methods as delegate params. Something like this:

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's Execute will call the code you wrote in Base then it will execute A then B and finally everything you declared after the for each in Base.

洋洋洒洒 2024-12-31 19:04:19

使用 中的 NonPublic 成员BindingFlags 以包含类中的所有方法:

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

Use the NonPublic member from BindingFlags to include all the methods in your class:

Me.GetType.InvokeMember(Stages(CurrentStage), 
                         BindingFlags.InvokeMethod Or BindingFlags.NonPublic, 
                         Nothing, 
                         Me, 
                         Nothing)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文