2013-07-18 12 views
4

我有一個共同的問題,即我試圖以特定的方式繞過。使用表達式,靜態方法和基礎對象獲取類的屬性名稱

基本上用Winforms,我試圖在表單中設置控件的「DisplayMember」和「ValueMember」。你通常會設置它像這樣:

this.testCombobox.DisplayMember = "PropertyOne"; 
this.testCombobox.ValueMember = "PropertyTwo"; 

我想改寫這個如下:

this.testCombobox.DisplayMember = ClassOne.GetPropertyName(c => c.PropertyOne); 
this.testCombobox.ValueMember = ClassOne.GetPropertyName(c => c.PropertyTwo); 

(注:2個的方法調用必須是靜態的,保存在這裏創建對象)

所有我的班,我試圖做到這一點,從基類「BaseObject」繼承,所以我增加如下的方法給它:

public static string GetPropertyName<T, P>(Expression<Func<T, P>> action) where T : class 
{ 
    MemberExpression expression = action.Body as MemberExpression; 
    return expression.Member.Name; 
} 

然而,爲了利用這一點,我需要編寫下面的代碼來代替:

this.testCombobox.DisplayMember = BaseObject.GetPropertyName((ClassOne c) => c.PropertyOne); 

我的問題是,我將如何改寫方法BaseObject.GetPropertyName達到我想要什麼?我覺得我非常接近,但不知道如何改變它。

回答

4

您當前的GetPropertyName方法會打開通用T.因此,編譯器無法解決它的編譯時間,因爲您在使用該方法時沒有指定它。然後,如果你讓你的基類是通用的,並且在派生類中指定了T,並且指定使用派生類(而不是基類)的方法,那麼它就可以工作。

像這樣:

public class BaseClass<T> { 
    public static string GetPropertyName<P>(Expression<Func<T, P>> action) { 
     MemberExpression expression = action.Body as MemberExpression; 
     return expression.Member.Name; 
    } 
} 

public class ClassOne : BaseClass<ClassOne> { 
    public string PropertyOne { get; set; } 
} 
public static class Test { 
    public static void test() { 
     var displayMember = ClassOne.GetPropertyName(x => x.PropertyOne); 
    } 
} 
+0

完美,就是這樣。謝謝馬丁! – eyeballpaul

4

我創建了一個助手類提取Proprty名稱

public static class PropertySupport 
    {  
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression) 
    { 
     if (propertyExpression == null) 
     { 
     throw new ArgumentNullException("propertyExpression"); 
     } 

     var memberExpression = propertyExpression.Body as MemberExpression; 
     if (memberExpression == null) 
     { 
     throw new ArgumentException("Invalide Expression", "propertyExpression"); 
     }    
     return memberExpression.Member.Name; 
    } 
    } 

而且可以按如下方式使用它:

PropertySupport.ExtractPropertyName(() => DateTime.Now) 

它會返回 「現在」

編輯

這是一個測試控制檯應用程序:

public static class PropertySupport 
    {  
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression) 
    { 
     if (propertyExpression == null) 
     { 
     throw new ArgumentNullException("propertyExpression"); 
     } 

     var memberExpression = propertyExpression.Body as MemberExpression; 
     if (memberExpression == null) 
     { 
     throw new ArgumentException("", "propertyExpression"); 
     }  
     return memberExpression.Member.Name; 
    } 
    } 
    public class MyClass 
    { 
    public MyClass PropertyOne { get; set; } 
    } 
    class Program 
    {  
    static void Main(string[] args) 
    {  
     Console.WriteLine(PropertySupport.ExtractPropertyName(() => new MyClass().PropertyOne)); 
     Console.ReadKey(); 
    } 
    } 
+0

而且你會如何調用這種方法獲取實際類的屬性名稱?我已經嘗試過你在這裏所擁有的東西,並且無法讓它起作用。 – eyeballpaul

+0

像PropertySupport.ExtractPropertyName(()=> YouClassInstance.Property)的簡單調用。我在我的所有項目中都使用它,它對我來說工作得很好。 – Swift

+0

好吧,這是我從未嘗試過的新對象的新興事物。 – eyeballpaul

0

我建議在通用幫手以下幾點:

public static class GenericHelper<TEntity> { 

     public static string GetPropertyName<TProperty>(Expression<Func<TEntity, TProperty>> propertyExpression) { 

      return propertyExpression.GetPropertyName(); 
     } 
    } 

和擴展的常見用法如下:

public static class ReflectionExtensions { 

    public static PropertyInfo GetProperty<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> source) { 

     //TODO: check TEntity, if needed. Now it's ignored 

     var member = source.Body as MemberExpression; 

     if (member == null) { 
      throw new ArgumentException(String.Format(
       "Expression '{0}' refers to a method, not a property.", source)); 
     } 

     var propertyInfo = member.Member as PropertyInfo; 

     if (propertyInfo == null) { 
      throw new ArgumentException(string.Format(
       "Expression '{0}' refers to a field, not a property.", source)); 
     } 

     return propertyInfo; 
    } 

    public static string GetPropertyName<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> source) { 

     return source.GetProperty().Name; 
    } 
} 
相關問題