3

我最近发现很多与在 C# 中引用泛型类相关的代码异味。我的抱怨尤其适用于那些从 DependencyObject 继承并包含 DependencyProperties 的类。

基本问题是,在声明依赖属性时,通常会引用当前类型,也称为owner。这工作得很好,通常对于简单的非泛型对象来说不是什么大问题,除非对象包含多个依赖属性,然后需要在不同的地方重构类型名称(通过重构更容易)视觉工作室)。

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 网站上提出了这个问题,但他们拒绝了自引用关键字的想法,但没有提供解决方法或替代解决方案。我的想法是使用一些关键字,例如OwnerOwnerClassThisType,以便泛指使用关键字的类型。

4

1 回答 1

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);

接下来,您可以使用这个巧妙的技巧来确保对 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);
于 2009-09-23T13:14:49.767 回答