如何确定函数定义中类的类型?

时间:2012-11-06 12:56:27

标签: vb.net linq linq-expressions

我不确定如何提出这个问题,但基本上我想知道如何一般地指定类类型,以便我可以输入和粘贴代码。

例如,我有以下代码:

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,但应根据已知的扩展方法中的其他信息轻松推断出该类型。

在过程定义中一般可能无法指定一个类类型,在这种情况下,我每次使用它时都会修改代码,但我宁愿不在这个过程中学习新的东西。

2 个答案:

答案 0 :(得分: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)

(未经测试 - 但无论如何都不起作用:-()

答案 1 :(得分: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)以包含派生类,那么NotifyPropertyChanged(Function(x) x.myChaningProperty)之类的调用也会起作用。

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