2009-06-20 5 views
11

私はクラスのプロパティとクラス自体に適用されるカスタム属性を持っています。私のカスタム属性を適用する必要があるすべてのクラスは、単一の基本クラスから派生しました。それが私の基本クラスから派生しなければなりませんのみのクラスに適用することができるように、私は私のカスタム属性を制限することができますどのようにC#の特定の型にのみ適用できるようにカスタム属性を制限しますか?

?これはどうすればいいですか?

abstract class MyBase { 
    [AttributeUsage(AttributeTargets.Property)] 
    protected sealed class SpecialAttribute : Attribute {} 
} 

class ShouldBeValid : MyBase { 
    [Special] 
    public int Foo { get; set; } 
} 
class ShouldBeInvalid { 
    [Special] // type or namespace not found 
    [MyBase.Special] // inaccessible due to protection level 
    public int Bar{ get; set; } 
} 

(オリジナルの答え:私は自分自身が間違っていることを証明するとき

+0

あなたは(それが自動的に行われるように)それを強制たり(それは他のタイプに適用することができないので)それを制限したいですか? –

+0

ベースクラスから派生したもの以外の型には適用できないように制限したいと思います。 –

+0

編集:まあ、私はそれを行う方法を見つけることによって自分自身を矛盾したと思う!私のための新しいもの... –

答えて

15

ダーン、私はあなたが基本クラスの保護ネストされたタイプと属性を定義する場合、それが動作...それを嫌います)

あなたはこれを行うことはできません - 少なくとも、コンパイル時ではなく。しかし、何よりも粒状 -

属性は、「クラス」、「構造体」、「方法」、「フィールド」、などに(exmapleのために)制限することができます。もちろん

、属性は自分で何もしないので、(あなたは、実行時に属性を見ていくつかのコードを追加しない限り、あなたのタイプの不活性)(PostSharpを無視して)、彼らは他の種類の不活性になります。

あなたはFxCopのルールを書くことができ、それはやり過ぎと思われます。

私は属性が最良の選択であるかどうか、しかし、不思議:

今私のカスタム属性を適用する必要があり、すべてのクラスは、単一の基本クラスから派生しています。彼らはカスタム属性を適用する必要があります場合

は、多分abstract(または多分ちょうどvirtual)プロパティ/メソッドは、より良い選択でしょうか?

abstract class MyBase { 
    protected abstract string GetSomeMagicValue {get;} 
} 
class MyActualType : MyBase { 
    protected override string GetSomeMagicValue {get {return "Foo";}} 
} 
+0

ありがとうmarc。私はマッピングのプロパティに属性を適用しています。基本クラスには、この属性が適用されている派生クラスのすべてのプロパティが返されます。さらに、重要な目的を持たないタイプやメンバーに属性を適用することは意味がありません。 –

+0

私は結論に達した前に、これを行うためのドキュメントを見つけられませんでした。私はstackoverflowでチャンスを与えたいと思っていました。私は、属性が意図的に適用されると考えています。なぜ、それが目的を持たないタイプまたはメンバーに適用されるのを許可するのですか? –

+0

"なぜそれを許可するのか" - 単純に、現時点ではそれを防ぐことはできません。それを禁止するメカニズムはありません。 –

0

カスタム属性でこれを行う方法はわかりません。
良い方法は

class MyAttribute 
{ 
    // put whatever custom data you want in here 
} 

interface IAttributeService<T> where T : MyBaseClass 
{ 
    MyAttribute Value{get;} 
} 

ので、一般的な制約で

をインターフェイスを実装するクラスを取得することです、あなたのベースクラスは、この

class MyBaseClass : IAttributeService<MyBaseClass> 
{ 
    private MyAttribute m_attrib; 

    IAttributeService<MyClass>.Value 
    { 
     get {return m_attrib;} 
    } 
} 

を行うだろう、コンパイラがすることを道コンパイル時に制約を適用して、MyBaseClassから派生したクラス
のみがインターフェイスを実装できるようにします。
私はMyAttributeクラスを定義することで、それはかなり拡張可能作られていますがシンプルな何か

を必要に応じて、派生クラスがそれを見ることができなかったように、あなたは、もちろん単なる文字列やブール値を返すことができ、私もMyAttributeメンバーのプライベートを作り、それを変更することができますが、それを保護することができますし、派生クラスのアクセスをしたい場合。

関連する問題