許可された属性を複製する方法


96

属性クラスから継承したカスタム属性を使用しています。私はそれを次のように使用しています:

[MyCustomAttribute("CONTROL")]
[MyCustomAttribute("ALT")]
[MyCustomAttribute("SHIFT")]
[MyCustomAttribute("D")]
public void setColor()
{

}

しかし、「重複した 'MyCustomAttribute'属性」エラーが表示されます。
許可された属性を複製するにはどうすればよいですか?

回答:


184

スティックAttributeUsage(一口だうん、)あなたのAttributeクラスに属性をセットAllowMultipleしますtrue

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class MyCustomAttribute: Attribute

6
ちょうど好奇心が強い-なぜ「封印された」クラスなのか?
Tomas Aschan

18
マイクロソフトは、可能な限り属性クラスをシールすることをお勧めします:msdn.microsoft.com/en-us/library/2ab31zeh.aspx
Anton Gogolev

3
なぜ封印されたのですか?つまり、属性の検索が高速になり、他の影響はありません。
Noel Widmer

ただし、他のユーザーがコードを再利用できないようにする必要があります。DataAnnotationsの検証属性がシールされていないことは注目に値します。これは、属性の特殊化を作成できるので非常に便利です。
ニュートリノ

@Neutrino Sealedは、クラスが継承されることを予期していない、または設計しない場合に使用する必要があります。さらに、継承がバグの原因となる可能性がある場合(例:スレッドセーフな実装)。
Francisco Neto

20

AttributeUsageAttribute ;-p

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MyAttribute : Attribute
{}

ただし、ComponentModel(TypeDescriptor)を使用している場合、メンバーごとに(属性タイプごとに)1つの属性インスタンスのみがサポートされることに注意してください。生の反射は任意の数をサポートしています...


13

アントンの解決策は正しいですが、別の落とし穴があります。

つまり、カスタムattrbiuteがTypeIdをオーバーライドしない限り、それを介してアクセスするとPropertyDescriptor.GetCustomAttributes()、属性の単一のインスタンスのみが返されます。


ただし、次のように機能します。var customAtt = propertyInfo.GetCustomAttributes <MyCustomAttribute>();
oo_dev 2018年

8

デフォルトでは、Attributesは単一のフィールド/プロパティなどに1回だけ適用されるように制限されています。これは、MSDN Attributeクラス定義から確認できます。

[AttributeUsageAttribute(..., AllowMultiple = false)]
public abstract class Attribute : _Attribute

したがって、他の人が指摘したように、すべてのサブクラスは同じ方法で制限され、同じ属性の複数のインスタンスが必要な場合は、明示的AllowMultipletrue次のように設定する必要があります。

[AttributeUsage(..., AllowMultiple = true)]
public class MyCustomAttribute : Attribute

複数の使用を許可する属性では、TypeIdプロパティオーバーライドして、などのプロパティがPropertyDescriptor.Attributes 期待どおりに機能することを確認する必要もあります。これを行う最も簡単な方法は、そのプロパティを実装して属性インスタンス自体を返すことです。

[AttributeUsage(..., AllowMultiple = true)]
public class MyCustomAttribute : Attribute
{
    public override object TypeId
    {
        get
        {
            return this;
        }
    }
}

(この回答を投稿するのは、他の回答が間違っているからではなく、より包括的/標準的な回答だからです。)


3

別の方法として、シーケンスを使用できるように属性を再設計することを検討してください。

[MyCustomAttribute(Sequence="CONTROL,ALT,SHIFT,D")]

または

[MyCustomAttribute("CONTROL-ALT-SHIFT-D")]

次に、値を解析して属性を構成します。

この例については、www.codeplex.com / aspnetでASP.NET MVCソースコードのAuthorizeAttributeを確認してください。


3
修飾子の有無にかかわらず、MyCustomAttributeコンストラクタに文字列の配列 aを使用させることもできます。次に、構文を使用して(を使用して)適用できます。string[]params[MyCustom("CONTROL", "ALT", "SHIFT", "D")]params
Jeppe Stig Nielsen

2

AttributeUsageを追加したら、必ずこのプロパティをAttributeクラスに追加してください

public override object TypeId
{
  get
  {
    return this;
  }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.