如何有效地打开表达式结果?

时间:2015-04-15 21:11:08

标签: .net vb.net generics lambda clr

我不确定我说得那么好,但我想做的就是这个。我使用来获得这样的代码:

Select Case name
  Case "ThisProperty": ...
  Case "ThatProperty": ...
  ...
End Select

name是对象的属性,我想以类型安全的方式执行此操作,因此如果属性更改,我会将其作为编译时错误捕获。所以我想要这种伪代码

Select Case name
  Case PropertyName(Of MyType)(Function(x) x.ThisProperty): ...
  Case PropertyName(Of MyType)(Function(x) x.ThatProperty): ...
  ...
End Select

,其中

Function PropertyName(Of T)(propertySpecifier As Expression(Of Func(Of T, Object))) As String
    Return {expression magic to get property name as a string}
End Function

我的PropertyName功能运行正常,但你不能像这样编码Select Case,即使你可以,我也担心这会非常低效,因为所有的表达操作,无论如何都是一个紧密的循环。 (而且语法也很乏味。)

所以我想知道是否有合理的方法对此进行编码以解决这两个问题。

3 个答案:

答案 0 :(得分:1)

正如我在评论中所说,NameOf运算符将成为即将推出的VB.NET 14中的优势,Visual Studio 2015即将推出。您不必担心效率问题因为它将在编译时进行评估,而不是在运行时使用反射。

与此同时,如果没有创建自己的代码生成预构建操作,最好的选择可能是仅通过反射评估属性名称,并缓存结果。例如,您可以创建一个操作字典,如下所示:

Dim actions As New Dictionary(Of String, Action)()
actions.Add(PropertyName(Of MyType)(Function(x) x.ThisProperty),
            Sub() Console.WriteLine("This"))
actions.Add(PropertyName(Of MyType)(Function(x) x.ThatProperty),
            Sub() Console.WriteLine("That"))

然后,而不是Select Case,您可以从字典中拉出所需的操作并执行它:

actions(name).Invoke()

至少那时你只需要在构建字典时获取属性名称一次。在它建成之后在字典中找到它们会非常快。但是,对于简短列表,您可能只想使用SortedList而不是Dictionary

答案 1 :(得分:1)

Steven Doggart所说的是对的。这是一个例子。我已经在我正在进行名称绑定表达式评估的情况下使用了NameOf,它替换了我的所有文字字符串,因此对名称重构具有弹性。

(FWIW,VS2015 CTP6 - (撰写本文时的当前版本) - 稳定且VB和C#都功能齐全)

Sub Main()
    Dim name = "x"

    Select Case name.ToUpperInvariant
        Case NameOf(Grover.x).ToUpperInvariant
            Console.WriteLine("Monkey")
        Case NameOf(Grover.y).ToUpperInvariant
            Console.WriteLine("Giraffe")
        Case NameOf(Grover.Cheese).ToUpperInvariant
            Console.WriteLine("Ferret")
    End Select

    Console.ReadKey()
End Sub

Public Class Grover
    Public x As Integer
    Public y As Integer
    Public Cheese As String
End Class

答案 2 :(得分:0)

这是一个正是为了这个目的的例程。它在C#中。 但VB。应该可以接受表达式的静态类的净等价物。也许有一个vb老兄知道如何转换它。

如何处理引用POCO属性的字符串并在更改时获得编译时错误。 你使用一个小的lamda表达式来引用属性,你得到的是名字作为字符串返回。

 public static class MyExtUtilites {
 public static string PropNameAsExpr<TPoco, TProp>(Expression<Func<TPoco, TProp>> prop)      {

        var body = prop.Body as System.Linq.Expressions.MemberExpression;
        return body == null ? null : body.Member.Name;
    }
  }

使用此属性作为字符串的属性名称是必需的。 在编译时,必须在MyPoco类中知道属性 propname

  var propNameAsString =  myExtUtilites.PropNameAsExpr((MyPoco p) => myPoco.propname)     ;

从随机网站执行c#到vb网络转换。不确定是否可以。

 Imports System
 Imports System.Linq
 Imports System.Linq.Expressions

 Public static Class MyExtUtilites
Public static String PropNameAsExpr<TPoco, TProp>(Expression<Func<TPoco, TProp> prop)      
{

    Dim body As var =  prop.Body as System.Linq.Expressions.MemberExpression 
    Return body  =  Nothing ? Nothing : body.Member.Name
}
End Class