我最近发现很多代码都与在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));
}
我最近发现的是,当将这种夸张的自我引用实践与广泛使用泛型相结合时,代码真的开始变得难看。
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的想法,但未提供解决方法或替代解决方案。我的想法是使用一些关键字,例如所有者, OwnerClass 或 ThisType ,以便一般性地引用关键字所在的类型使用
答案 0 :(得分: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);