Не могу подумать о частных методах - PullRequest
0 голосов
/ 05 января 2012

Итак, я создал этот поток: Вызов частных / защищенных методов с помощью отражения от одного и того же экземпляра объекта (или базы)

И мы получили исправленную проблему, за исключением частных методов.Поскольку это может быть не та проблема, я подумал, что лучше будет опубликовать другой вопрос с полным исходным кодом.Это все еще в стадии разработки, но это функционально.

Базовый класс:

Public MustInherit Class BaseTransactionalSaveManager : Implements ITransactionalSaveManager

    '---- Public Properties & Backing Fields ----'

    Public Property FormDataIsValid As Boolean Implements ITransactionalSaveManager.FormDataIsValid

    '---- Private Properties & Backing Fields ----'

    Protected Property Stages As Collections.Generic.List(Of String)
    Protected Property StageCausedRollback As Containers.GenericNamedValuePair(Of String, Boolean)
    Protected Property CurrentStage As Integer

    '---- Event Declarations & Associated Methods ----'

    Public Event TransactionCancelled As EventHandler(Of CustomEventArgs.GenericSingleEventArgs(Of String)) Implements ITransactionalSaveManager.TransactionCancelled

    Public Event TransactionCompleted As EventHandler(Of CustomEventArgs.GenericSingleEventArgs(Of String)) Implements ITransactionalSaveManager.TransactionCompleted

    Public Event TransactionStagePassed As EventHandler(Of CustomEventArgs.GenericSingleEventArgs(Of String)) Implements ITransactionalSaveManager.TransactionStagePassed

    Protected Overridable Sub OnTransactionCancelled(e As CustomEventArgs.GenericSingleEventArgs(Of String)) Implements ITransactionalSaveManager.OnTransactionCancelled

        RaiseEvent TransactionCancelled(Me, e)

    End Sub

    Protected Overridable Sub OnTransactionCompleted(e As CustomEventArgs.GenericSingleEventArgs(Of String)) Implements ITransactionalSaveManager.OnTransactionCompleted

        RaiseEvent TransactionCompleted(Me, e)

    End Sub

    Protected Overridable Sub OnTransactionStagePassed(e As CustomEventArgs.GenericSingleEventArgs(Of String)) Implements ITransactionalSaveManager.OnTransactionStagePassed

        RaiseEvent TransactionStagePassed(Me, e)

    End Sub

    '---- Constructors ----'

    Public Sub New()

        Stages = New Collections.Generic.List(Of String)
        SetStages()
        CurrentStage = 0

        StageCausedRollback = New Containers.GenericNamedValuePair(Of String, Boolean)
        FormDataIsValid = True

    End Sub

    '---- Public Methods ----'

    Public Sub ProcessStage() Implements ITransactionalSaveManager.ProcessStage

        ' Use stage to fire the correct method.

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

        ' Determine if the stage should cause a rollback.

        If Not StageCausedRollback.Value Then

            RollBackTransaction(StageCausedRollback.Name)
            Exit Sub

        End If

        ' Check if this stage is the last one.

        If Stages(CurrentStage) = Stages.Last Then

            OnTransactionCompleted(New CustomEventArgs.GenericSingleEventArgs(Of String)(Stages(CurrentStage)))

        Else

            OnTransactionStagePassed(New CustomEventArgs.GenericSingleEventArgs(Of String)(Stages(CurrentStage)))

        End If

    End Sub

    Public Overridable Function TryCancelTransaction() As Boolean Implements ITransactionalSaveManager.TryCancelTransaction

        OnTransactionCancelled(New CustomEventArgs.GenericSingleEventArgs(Of String)(""))
        Return True

    End Function

    '--- Protected & Overridable Methods ----'

    Protected Overridable Sub SetStages()

        Me.Stages.Add(MethodNameToString(AddressOf Me.ConfirmFormDataIsValid))

    End Sub

    Protected Overridable Sub RollBackTransaction(stageThatCauseRollback As String)

        OnTransactionCancelled(New CustomEventArgs.GenericSingleEventArgs(Of String)(stageThatCauseRollback))

    End Sub

    Protected Function MethodNameToString(addressOfMethod As Action) As String

        Return addressOfMethod.Method.Name

    End Function

    Private Sub ConfirmFormDataIsValid()

        StageCausedRollback.Name = MethodNameToString(AddressOf ConfirmFormDataIsValid)
        StageCausedRollback.Value = If(FormDataIsValid, True, False)

    End Sub

End Class

Таким образом, этот класс наследуется (пока что) пустым дочерним классом, а ProcessStage находитсяназывается.Обратите внимание, что подпрограмма ConfirmFormDataIsValid () является закрытой.Если вы запустите это, он не найдет этот метод.Если я изменю его на защищенный, он будет работать нормально.

Я что-то упустил?

Ответы [ 2 ]

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

Вместо Me.GetType.InvokeMember (первая строка ProcessStage) вам нужно вызвать Me.GetType.BaseType.InvokeMember

Вы не увидите приватных членов в подклассах, даже с BindingFlags.NonPublic.

Очевидно, что это решение будет немного хрупким, так как оно зависит от того, сколько уровней у вас подклассов, в зависимости от того, увидите ли вы метод в BaseType или нет.Возможно, вам придется зациклить цепочку классов, пока вы не достигнете базового типа BaseTransactionalSaveManager, а затем найдете метод.

Надеюсь, это поможет.

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

Это действительно не отвечает на ваш вопрос, но, надеюсь, даст вам некоторое вдохновение для использования Шаблонного шаблона.

Во-первых, вы нарушаете DRY, используя методы и , создавая список имен этих методов. Теперь, если вы делаете метод переименования, вы должны изменить его в 2 местах.

Используя шаблон шаблонов методов, вы предоставляете абстрактный метод, в котором дочерний класс определяет все методы, которые они хотят вызвать, и в правильном порядке (заменяя список, который они предоставляют сейчас). Вы теряете все затраты на рефлексию этих методов, и разработчики больше не ограничены никакими параметрами методов.

Кроме того, если есть хороший способ что-то сделать без отражения, обычно это более чистое и понятное решение.

- CW, потому что это действительно очень длинный комментарий и он не отвечает на поставленный вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...