代码之家  ›  专栏  ›  技术社区  ›  jpierson

有没有更好的自我引用类型的方法?

  •  3
  • jpierson  · 技术社区  · 15 年前

    最近我发现有很多代码气味与引用C中的泛型类有关。我的gripes特别适用于从DependencyObject继承并包含DependencyProperties的类。

    基本问题是,当声明依赖属性时,通常引用当前类型,也就是 主人 . 这很好地工作,一般来说,对于简单的非泛型对象来说,这不是什么问题,除了当对象包含多个依赖属性,然后需要在不同的地方重新考虑类型名(在Visual Studio中重构更容易)。

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

    不过,我最近发现,当将这种burdon的一些明确的自引用实践与大量使用泛型相结合时,代码确实开始变得丑陋起来。

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

    我的问题是,是否有人知道任何技巧、黑客或合法的解决方案,以减少在上面所示的情况下需要引用具有通用参数的完整类型名称的次数。

    完全公开:我在微软提出了这个问题。Connect网站,但他们拒绝了 self referencing keyword 但没有提供解决方案或替代方案。我的想法是使用一些关键字,比如 业主 , 所有者类别 这种类型 为了一般地引用使用关键字的类型。

    1 回复  |  直到 15 年前
        1
  •  3
  •   Community datashaman    7 年前

    你可以做一些事情来减轻疼痛。创建一个静态变量,该变量包含当前类的类型信息。

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