Invoking Private / Protected Methods Via Reflection From The Same Object Instance (or Base)

15,874

Solution 1

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.

Solution 2

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.

Solution 3

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)
Share:
15,874
deanvmc
Author by

deanvmc

Updated on July 17, 2022

Comments

  • deanvmc
    deanvmc almost 2 years

    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).