3

私のプロジェクトの 1 つに次のようなコード サンプルがあります...

    [Obfuscation(Exclude = true)]
    [UsedImplicitly]
    public DelegateCommand<object> OpenXCommand { get; private set; }

私は、属性がコードに多くの「ノイズ」を追加していることを発見しました.1つのクラスにこのような複数のプロパティがあり、すべて同じ属性装飾を持つ可能性があるため、DRY原則に違反していることもわかります。

Q: サブ属性の組み合わせを表す属性を設定する方法はありますか?

理想的には、このようなものが欲しい..

    [MyStandardCommandAttribute]
    public DelegateCommand<object> OpenXCommand { get; private set; }

以前に独自の属性を実装したことがないため、これが可能かどうかはわかりません。助言がありますか?

4

2 に答える 2

3

いいえ。あなたの 1 つの属性を同時に"be" にすることはできませんObfuscation( C# には多重継承はありません)。UsedImplicitly

eg を探しているコードは、それが表すはずUsedImplicitlyAttributeのものを知る方法がありません(これらの属性をすべて使用してすべてのコードを制御しない限り)。MyStandardCommandAttributeUsedImplicitlyAttribute

于 2013-02-12T01:26:57.367 に答える
2

残念ながら、C# でこれを行う方法はありません。

ただし、これらの属性を読み取る場所を (リフレクションを使用して) コントロールする場合は、規則に従って行うことができます。

たとえば、プロキシする属性で属性に「注釈を付ける」マーカー インターフェースを使用できます (メタ属性のように聞こえます)。

public interface AttributeProxy<T> 
  where T : Attribute {}

public class MyStandardCommandAttribute : 
  Attribute, 
  AttributeProxy<ObfuscationAttribute>, 
  AttributeProxy<UsedImplicitlyAttribute> {}

(もちろん、正しいAttributeUsages も一致させる必要があります。また、このようにプロキシされた属性にプロパティを設定することはできません。)

ここで、さらに一歩進んで、Mono.Cecil などの IL 操作ライブラリを使用して、コンパイル後のステップで実際に属性を適切に転送することができます。この場合、これらの属性を反映していなくても機能します。

更新: 引き続き独自の属性を反映するシナリオでは、以下のコードを使用して、プロキシされた属性を取得し、プロパティ値を設定することもできます。

public interface IAttributeProxy {
  Attribute[] GetProxiedAttributes();
}

public class MyStandardCommandAttribute : Attribute, IAttributeProxy {
  public Attribute[] GetProxiedAttributes() {
    return new Attribute[] {
      new ObfuscationAttribute { Exclude = true },
      new UsedImplicitlyAttribute()
    };
  }
}

リフレクション コードで次の拡張メソッドを使用します。

public static object[] GetCustomAttributesWithProxied(this MemberInfo self, bool inherit) {
  var attributes = self.GetCustomAttributes(inherit);
  return attributes.SelectMany(ExpandProxies).ToArray();
}

private static object[] ExpandProxies(object attribute) {
  if (attribute is IAttributeProxy) {
    return ((IAttributeProxy)attribute).GetProxiedAttributes().
      SelectMany(ExpandProxies).ToArray(); // don't create an endless loop with proxies!
  }
  else {
    return new object[] { attribute };
  }
}
于 2013-02-12T01:46:53.330 に答える