2

この質問をする方法はよくわかりませんが、基本的には、コードを入力して貼り付けることができるように、クラスタイプを一般的に指定する方法を知りたいと思います。

たとえば、次のコードがあります。

Public Class CustInfo
    Implements INotifyPropertyChanged

    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Protected Sub NotifyPropertyChanged(ByVal Name As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Name))
    End Sub

    Protected Sub NotifyPropertyChanged()
        Dim myStackFrame As New StackFrame(1)
        Dim myChangingPropertyName As String = myStackFrame.GetMethod.Name.Split("_")(1)
        NotifyPropertyChanged(myChangingPropertyName)
    End Sub

    Protected Sub NotifyPropertyChanged(Of TResult)(propertyExpr As Expression(Of Func(Of CustInfo, TResult)))
        NotifyPropertyChanged(Me.GetPropertySymbol(propertyExpr))
    End Sub

アイデアは、最後のSubものを一般的なものにすることです。つまり、その定義でCustInfoを具体的に指定する必要はありません。このようにして、このコードを文字通り他のクラスにコピーすることができ、変更せずに動作します。

クラスの型を返すプロパティを作成して使用しようとしましたが、予想通り失敗しました。TypeOf、Me、さらには「これ」をロングショットで使用してみましたが、何も機能しませんでした。最後のサブを次のように変更したときに表示されるこのエラーメッセージに基づいて、コンパイラがこれを知る方法が必要なようです。

Protected Sub NotifyPropertyChanged(Of TResult)(propertyExpr As Expression(Of Func(Of TResult)))
    NotifyPropertyChanged(Me.GetPropertySymbol(propertyExpr))
End Sub

Data type(s) of the type parameter(s) in extension method 'Public Function GetPropertySymbol(Of TResult)(expr As System.Linq.Expressions.Expression(Of System.Func(Of CustInfo, TResult))) As String' defined in 'CustClasses.Extensions' cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.

参照されている拡張メソッドは次のとおりです。

<Extension()>
Public Function GetPropertySymbol(Of T, TResult)(obj As T, expr As Expression(Of Func(Of T, TResult))) As String
    Return DirectCast(expr.Body, MemberExpression).Member.Name
End Function

したがって、ご覧のとおり、コンパイラは何が起こっているかを正しく推測しましたが、それでも動作できませんでした。不明と思われる唯一のタイプはTResultですが、そのタイプは、既知の拡張メソッドの他の情報に基づいて簡単に推測できるはずです。

プロシージャ定義でクラスタイプを一般的に指定することは不可能かもしれません。その場合、コードを使用するたびにコードを変更しますが、その過程で何か新しいことを学びたくはありません。

4

2 に答える 2

1

編集:記載されているように動作しません。T Asを呼び出すことができるように指定するものがまだ必要です.NotifyPropertyChanged。このためのインターフェースを定義できますか?


メソッドと供給に「デモート」NotifyPropertyChanged(Of TResult)して、そのタイプを暗黙的に許可することができます。ここで、それは次のように呼ばれます。SharedMe

Shared Protected Sub NotifyPropertyChanged(Of T, TResult)(This As T, propertyExpr As Expression(Of Func(Of T, TResult)))
    This.NotifyPropertyChanged(This.GetPropertySymbol(propertyExpr))
End Sub

そして今、電話は

NotifyPropertyChanged(Me, myChangingPropertyName)

(テストされていません-しかし、とにかく動作しません:-()

于 2012-11-07T14:23:34.157 に答える
1

@Mark Hurdの回答に基づいて、プロパティの操作をはるかに簡単にするものを考え出しました。MustInheritそのImplementsで装飾され、再利用と移植性を最大化するためにジェネリックスでセットアップするために必要なすべてINotifyPropertyChangedのコードを含むクラスを作成することにしました。NotifyPropertyChangedこのソリューションに関するフィードバックをお待ちしています。問題はありませんが、簡単に見落としている可能性があります。

Public MustInherit Class AutomaticNotfiyPropertyChanged
    Implements INotifyPropertyChanged

    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Protected Sub NotifyPropertyChanged(ByVal Name As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Name))
    End Sub

    Protected Sub NotifyPropertyChanged()
        Dim myStackFrame As New StackFrame(1)
        Dim myChangingPropertyName As String = myStackFrame.GetMethod.Name.Split("_")(1)
        NotifyPropertyChanged(myChangingPropertyName)
    End Sub

    Protected Shared Sub NotifyPropertyChanged(This As AutomaticNotfiyPropertyChanged, Name As String)
        This.NotifyPropertyChanged(Name)
    End Sub

    Protected Overridable Sub NotifyPropertyChanged(Of TResult)(propertyExpr As Expression(Of Func(Of AutomaticNotfiyPropertyChanged, TResult)))
        NotifyPropertyChanged(GetPropertySymbol(propertyExpr))
    End Sub

    Protected Shared Sub NotifyPropertyChanged(Of T, TResult)(This As T, propertyExpr As Expression(Of Func(Of T, TResult)))
        Dim myParent As AutomaticNotfiyPropertyChanged = TryCast(This, AutomaticNotfiyPropertyChanged)

        If myParent IsNot Nothing Then
            AutomaticNotfiyPropertyChanged.NotifyPropertyChanged(DirectCast(myParent, AutomaticNotfiyPropertyChanged), This.GetPropertySymbol(propertyExpr))
        End If
    End Sub

End Class

次に、他のプロパティの変更を通知するための呼び出しは、NotifyPropertyChanged(Me, Function(x) x.myChangingProperty)または現在のプロパティが変更されていることを通知する場合は、必要なすべてがですNotifyPropertyChanged()。さらにNotifyPropertyChanged(Me, "myChaningProperty")NotifyPropertyChanged("myChangingProperty")また動作します。最後に、NotifyPropertyChanged(Of TResult)がオーバーライドされて派生クラスが含まれる場合は、likeの呼び出しNotifyPropertyChanged(Function(x) x.myChaningProperty)も機能します。

NotifyPropertyChanged(Me, Function(x) x.myChaningProperty)また、それは問題なく動作し、コンパイラによってチェックされることがわかりました。ただし、IntelliSenseはでは機能しませんxxコンパイラーは変数の大文字化さえ修正するので、それが何であるかを明確に知っているので、私はそれが奇妙だと思います。NotifyPropertyChanged(Of TResult)これは大したことではありませんが、現在のクラスを反映するようにオーバーライドすると、IntelliSenseが機能します。

于 2012-11-12T21:36:46.257 に答える