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,甚至是“this”,但没有任何效果。似乎必须有一种方法让编译器根据我将最后一个子更改为时收到的此错误消息来了解这一点:

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

根据@Mark Hurd 的回答,我想出了一些让使用属性变得更加容易的方法。我决定创建一个类,用它装饰MustInheritINotifyPropertyChanged并包含所有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)被覆盖以包含派生类,那么类似的调用也NotifyPropertyChanged(Function(x) x.myChaningProperty)将起作用。

另外,我发现它NotifyPropertyChanged(Me, Function(x) x.myChaningProperty)可以正常工作,并且会被编译器检查。但是,IntelliSense 不适用于x. 我觉得这很奇怪,因为编译器清楚地知道是什么x,因为它甚至会更正变量的大小写。它不会破坏交易,但覆盖NotifyPropertyChanged(Of TResult)以反映当前类将使 IntelliSense 工作。

于 2012-11-12T21:36:46.257 回答
1

编辑:不按规定工作。您仍然需要指定一些T As内容以允许它调用.NotifyPropertyChanged. 你能为此定义一个接口吗?


您可以“降级”NotifyPropertyChanged(Of TResult)Shared方法和供应Me,从而允许隐含它的类型,它被称为:

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 回答