Вызов частных / защищенных методов с помощью отражения от одного и того же экземпляра объекта (или базы) - PullRequest
10 голосов
/ 05 января 2012

Можно ли вызвать защищенный метод с помощью отражения. Я использую это:

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

Который всегда вызывает метод без параметров или возврата. Идея состоит в том, что пользователь моего объекта (транзакционная обработка бизнес-логики) наследует базовый класс, добавляющий множество закрытых методов для запуска. Затем они добавляют имена этих методов в список в том порядке, в котором они хотели бы, чтобы они запускались, а код выше позаботится об их запуске.

Он отлично работает с открытыми методами, но не с закрытыми или защищенными методами в одном и том же классе (Защищено, потому что у меня есть некоторые «стандартные» предварительно созданные методы для добавления в базовый класс). Реально я мог бы обнародовать методы и покончить с этим, но мой внутренний ботаник не позволил бы мне сделать это ...

Я предполагаю, что это функция безопасности. Есть ли способ обойти это или у кого-нибудь есть какие-либо предложения о том, как действовать дальше, но держите мои вкусные, вкусные модификаторы видимости в такте?

(ПРИМЕЧАНИЕ: ЕГО В VB.NET, но ответ C # - это хорошо, если это то, с чем вам удобно).

Ответы [ 3 ]

13 голосов
/ 05 января 2012

Если вы вызываете методы для экземпляра объекта, вам также понадобится BindingFlags.Instance. Таким образом, код будет выглядеть следующим образом (Примечание: я также добавил опцию BindingFlags для включения открытых членов в поиск):

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

Подробнее об этом см. В документации MSDN .

EDIT

Для поддержки этого ответа я написал тестовую программу, которая демонстрирует вызов методов классов public, protected и private. Я загрузил все классы в PasteBin. Существует три класса, составляющих консольное приложение C #, поэтому их можно добавить в решение Visual Studio и запустить для тестирования.

  • Program.cs - Устанавливает методы, которые будут вызываться (содержатся в классе SomeClass). Выполняет вызов и печатает результаты.
  • SomeClass.cs - содержит три метода каждого из модификаторов видимости: public, protected и private. Также регистрирует себя и три содержащихся метода для вызова классом Invoker.
  • Invoker.cs - Принимает регистрацию типов и методов, которые должны быть вызваны. Затем перечисляет зарегистрированные типы и вызывает методы, создавая перечисляемую коллекцию результатов.

Не стесняйтесь просмотреть этот код и посмотреть, сможете ли вы найти какие-либо различия в подходах к нему. Я ценю, что это может быть не самым простым подходом, хотя. Дайте мне знать, если у вас есть еще вопросы по этому поводу.

5 голосов
/ 05 января 2012

Вам может не понадобиться рефлексия для этого. Может быть, я неправильно понял, чего вы хотели достичь, но звучит так, будто вы хотите внедрить кучу методов в другой метод, вроде как обернуть их. Вы можете передать приватные методы в качестве параметров делегата. Примерно так:

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 вызовет код, который вы написали в Base, затем выполнит A, затем B и, наконец, все, что вы объявили после для каждого в Base.

2 голосов
/ 05 января 2012

Используйте член NonPublic из BindingFlags, чтобы включить все методы в ваш класс:

Me.GetType.InvokeMember(Stages(CurrentStage), 
                         BindingFlags.InvokeMethod Or BindingFlags.NonPublic, 
                         Nothing, 
                         Me, 
                         Nothing)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...