2015-04-15 2 views
2

Я не уверен, что я так хорошо формулирую, но я хочу это сделать. Я использовал иметь такой код:Как я могу эффективно использовать результат выражения?

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, как это, и даже если вы можете, я опасаясь, что это будет действительно неэффективно, в жесткой петле, в любом случае, из-за всех манипуляций с выражениями. (И синтаксис действительно утомительный.)

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

+0

С какими ценностями вы имеете дело? Может быть, попробуйте перечислить? –

+1

Это будет намного проще в [VB.NET 14] (http://blogs.msdn.com/b/vbteam/archive/2014/12/09/new-language-features-in-visual-basic-14. aspx) (VS 2015), поскольку они добавляют оператор 'NameOf'. –

+0

@JacobRoberts: Тогда мне просто нужно обновить Enum вручную, когда имя свойства изменится, что просто изменит проблему где-то еще. То, что я пытаюсь сделать, это заставить компилятор автоматически поймать его, когда я что-то изменил. –

ответ

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

Что сказал Стивен Доггарт. Вот пример. Я уже использовал 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 
+0

Ох, это прекрасно. Я вижу, как «NameOf» будет делать вещи намного лучше. –

0

Здесь рутина именно для этой цели. Он находится на C#. Но VB. Чистый эквивалент статического класса, который принимает выражение, должен быть возможен. Возможно, есть vb dude, который знает, как его преобразовать.

Как обрабатывать строки, относящиеся к свойствам 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.

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

От случайного веб-сайта, который преобразует C# в vb net. Не уверен, что его ОК.

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 
+1

Вот что делает моя функция 'PropertyName', и она отлично работает. Мой вопрос заключается в том, как использовать это эффективно (т. Е. Вызов подпрограммы в узком цикле, вероятно, будет медленным) и как использовать его с синтаксисом Select Case/switch, где этот синтаксис будет неудобным или даже не будет компилировать –

+0

, если вы беспокоитесь о скорости, тогда предварительная фаза построения словаря может быть хорошим вариантом. Извините, что вы хотите, чтобы код не цитировался, –

Смежные вопросы