2009-09-22 75 views
3

我最近發現很多與C#中引用泛型類相關的代碼氣味。我的抱怨尤其適用於從DependencyObject繼承幷包含DependencyProperties的類。有沒有更好的方法來自我引用一個類型?

基本問題是,當聲明一個依賴屬性時,通常會引用當前類型,也就是所謂的所有者。這工作得很好,一般來說,對於簡單的非泛型對象來說問題不大,除了當對象包含多個依賴項屬性時,然後需要在各個地方重新考慮類型名稱(通過重構視覺工作室)。

public class MyDependencyObject : DependencyObject 
{ 
    public int MyProperty 
    { 
     get { return (int)GetValue(MyPropertyProperty); } 
     set { SetValue(MyPropertyProperty, value); } 
    } 

    public static readonly DependencyProperty MyPropertyProperty = 
     DependencyProperty.Register("MyProperty", typeof(int), typeof(MyDependencyObject), new UIPropertyMetadata(0)); 
} 

我一直在尋找最近雖然是這個burdonsome明確自參照慣例與廣泛使用泛型的結合,當代碼真的開始變得難看。

public class MyDependencyObject<TypeA, TypeB, TypeC, TypeD> : DependencyObject 
{ 
    public int MyProperty1 
    { 
     get { return (int)GetValue(MyPropertyProperty1); } 
     set { SetValue(MyPropertyProperty1, value); } 
    } 

    public static readonly DependencyProperty MyPropertyProperty1 = 
     DependencyProperty.Register("MyProperty1", typeof(int), typeof(MyDependencyObject<TypeA, TypeB, TypeC, TypeD>)); 

    public int MyProperty2 
    { 
     get { return (int)GetValue(MyPropertyProperty2); } 
     set { SetValue(MyPropertyProperty2, value); } 
    } 

    public static readonly DependencyProperty MyPropertyProperty2 = 
     DependencyProperty.Register("MyProperty2", typeof(int), typeof(MyDependencyObject<TypeA, TypeB, TypeC, TypeD>)); 

    public int MyProperty3 
    { 
     get { return (int)GetValue(MyPropertyProperty3); } 
     set { SetValue(MyPropertyProperty3, value); } 
    } 

    public static readonly DependencyProperty MyPropertyProperty3 = 
     DependencyProperty.Register("MyProperty3", typeof(int), typeof(MyDependencyObject<TypeA, TypeB, TypeC, TypeD>)); 

    public int MyProperty4 
    { 
     get { return (int)GetValue(MyPropertyProperty4); } 
     set { SetValue(MyPropertyProperty4, value); } 
    } 

    public static readonly DependencyProperty MyPropertyProperty4 = 
     DependencyProperty.Register("MyProperty4", typeof(int), typeof(MyDependencyObject<TypeA, TypeB, TypeC, TypeD>)); 
} 

我的問題是是否有人知道任何技巧,黑客,或者合法的解決方案,以減少與通用參數完整的類型名稱需要的情況下被引用的次數,如上面所示。

完全披露:我確實在Microsoft .Connect網站上提出這個問題,但他們拒絕了self referencing keyword的想法,但沒有提供解決方法或替代解決方案。我的想法是使用一些關鍵字,如所有者,所有者類別此類型爲了一般地指代關鍵字的使用類型。

回答

3

有幾件事情可以緩解疼痛。創建一個包含當前類的類型信息的靜態變量。

private static readonly Type ThisType = typeof(MyDependencyObject<TypeA, TypeB, TypeC, TypeD>)); 

public int MyProperty1 
{ 
    get { return (int)GetValue(MyPropertyProperty1); } 
    set { SetValue(MyPropertyProperty1, value); } 
} 

public static readonly DependencyProperty MyPropertyProperty1 = 
    DependencyProperty.Register("MyProperty1", typeof(int), ThisType); 

接下來,您可以使用this巧招,使引用您的getter和setter方法重構安全。

private static string GetPropertyName<TSource, TResult>(Expression<Func<TSource, TResult>> expression) 
{ 
    if (expression.NodeType == ExpressionType.Lambda && expression.BodyType == ExpressionType.MemberAccess) 
    { 
    PropertyInfo pi = (expression.Body as MemberExpression).Member as PropertyInfo; 
    if (pi != null) 
    { 
     return pi.Name; 
    } 
    } 
    throw new ArgumentException("expression", "Not a property expression."); 
} 

現在你的代碼會這樣。

private static readonly Type ThisType = typeof(MyDependencyObject<TypeA, TypeB, TypeC, TypeD>)); 

public int MyProperty1 
{ 
    get { return (int)GetValue(MyPropertyProperty1); } 
    set { SetValue(MyPropertyProperty1, value); } 
} 

public static readonly DependencyProperty MyPropertyProperty1 = 
    DependencyProperty.Register(GetPropertyName((MyDependencyObject x) => x.MyProperty1), typeof(int), ThisType); 
+0

使用靜態變量的好主意。但仍然有兩個問題。 1.我不能在所有類或至少那些從某些基類繼承的類中茫然應用靜態成員,所以我必須爲每個我編寫的DependencyObject編寫一個像這樣的變量。 2.另一個問題是當您需要將該類型作爲其他方法或類型聲明的泛型參數引用時。 總而言之,我認爲您的解決方案需要最少的代碼來生成靜態變量,並且還允許命名的靈活性,這非常好。 – jpierson 2009-09-23 14:39:53

相關問題