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

私が最近見つけたのは、この面倒な明示的な自己参照の慣行とジェネリックの広範な使用を組み合わせると、コードが本当に醜くなり始めるということです。

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 サイトの問題として提起しましたが、自己参照キーワードのアイデアを拒否しましたが、回避策や代替ソリューションは提供しませんでした. 私の考えは、キーワードが使用されている型を一般的に参照するために、 OwnerOwnerClass、またはThisTypeなどのキーワードを使用することでした。

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

次に、この巧妙なトリックを使用して、ゲッターとセッターへの参照を安全にリファクタリングできます。

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 に答える