2012-07-06 73 views
2

我有以下的擴展方法:從linq表達式中檢索信息時使用反射嗎?

public static string ToPropertyName<T,E>(this Expression<Func<E, T>> propertyExpression) 
{ 
    if (propertyExpression == null) 
     return null; 

    string propName; 
    MemberExpression propRef = (propertyExpression.Body as MemberExpression); 
    UnaryExpression propVal = null; 

    // -- handle ref types 
    if (propRef != null) 
     propName = propRef.Member.Name; 
    else 
    { 
     // -- handle value types 
     propVal = propertyExpression.Body as UnaryExpression; 
     if (propVal == null) 
      throw new ArgumentException("The property parameter does not point to a property", "property"); 
     propName = ((MemberExpression)propVal.Operand).Member.Name; 
    } 

    return propName; 
} 

我使用LINQ表達傳遞屬性名稱時的字符串而不是提供強有力的打字和我用這個功能來檢索屬性作爲字符串的名稱。此方法是否使用反射?

我的理由是這個方法在我們的代碼中使用了很多,我希望它足夠快。

+0

也看到http://stackoverflow.com/questions/4803272/in-c-is-expression-api-better-than-reflection?lq=1 – nawfal 2013-02-03 08:47:07

+0

[基於lambda表達式的反射vs普通反射]的可能重複(http:// stackoverflow。COM /問題/ 2697655 /λ-表達爲基礎的反射-VS-正常反射) – nawfal 2013-04-17 10:38:24

回答

2

據我所知,反射並不涉及某種動態類型內省在幕後發生的意義。但是,來自System.Reflection的類型(如TypePropertyInfo)與來自System.Linq.Expressions名稱空間的類型一起使用。它們僅供編譯器用來描述作爲抽象語法樹(AST)傳遞給您的方法的任何Func<T,E>。由於這個從Func<T,E>到表達式樹的轉換是由編譯器完成的,而不是在運行時完成的,所以只描述lambda的靜態方面。

請記住,在運行時從lambda構建這個表達式樹(複雜對象圖)可能需要比傳遞一個屬性名稱字符串(單個對象)稍長一些,只是因爲需要實例化更多的對象取決於傳遞給你方法的lambda的複雜性),但是再次涉及不涉及動態類型檢查。

例子:

This MSDN article顯示以下lambda表達式:

Expression<Func<int, bool>> lambda1 = num => num < 5; 

是由編譯器轉化爲這樣的事情:

ParameterExpression numParam = Expression.Parameter(typeof(int), "num"); 
ConstantExpression five = Expression.Constant(5, typeof(int)); 
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five); 
Expression<Func<int, bool>> lambda1 = 
    Expression.Lambda<Func<int, bool>>(
     numLessThanFive, 
     new ParameterExpression[] { numParam }); 

除此之外,沒有什麼事情發生。所以這是可能會傳入您的方法的對象圖。

0

由於你的方法命名是ToPropertyName,我想你試圖獲得類的某些特定屬性的類型名稱。你有沒有基於Expression<Func<E, T>>方法?創建表達式的代價是非常大的,因爲你的方法是靜態的,所以我看到你也沒有緩存成員表達式。換句話說,即使表達式方法不使用反射,成本也可能很高。看到這個問題:How do you get a C# property name as a string with reflection?,你有另一種方法:

public static string GetName<T>(this T item) where T : class 
{ 
    if (item == null) 
     return string.Empty; 

    return typeof(T).GetProperties()[0].Name; 
} 

你可以用它來獲得的財產或變量名,如:

new { property }.GetName(); 

爲進一步加快,你需要緩存成員信息。如果你有什麼是絕對Func<E, T>那麼你的方法適合。也看到這一點:lambda expression based reflection vs normal reflection

一個相關的問題:Get all the property names and corresponding values into a dictionary