限制自定义属性,以便它只能应用于C#中的特定类型?

时间:2009-06-20 07:57:41

标签: inheritance attributes c#-2.0

我有一个自定义属性,它应用于类属性和类本身。现在,必须应用我的自定义属性的所有类都派生自一个基类。

如何限制我的自定义属性,以便它只能应用于那些必须从我的基类派生的类?我该怎么做?

2 个答案:

答案 0 :(得分:15)

Darn,我讨厌当我证明自己错了......如果你将属性定义为基类的受保护的嵌套类型,它就会起作用:

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

(原始答案)

你不能这样做 - 至少,不是在编译时。

属性可以限制(例如)“class”,“struct”,“method”,“field”等 - 但不能更精细。

当然,由于属性本身不做任何事情(忽略PostSharp),它们对其他类型是惰性的(并且对你的类型不敏感,除非你在运行时添加一些代码来查看属性)。

你可以编写一个FxCop规则,但这似乎有些过分。

但我想知道属性是否是最佳选择:

  

现在,必须应用我的自定义属性的所有类都派生自一个基类。

如果他们必须应用您的自定义属性,那么abstract(或者只是virtual)属性/方法可能是更好的选择吗?

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

答案 1 :(得分: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类使它变得相当可扩展,但是如果你需要更简单的东西,你当然可以返回一个字符串或一个bool

我还将MyAttribute成员设为私有,以便派生类无法看到它并更改它但可以使其受到保护并允许派生类访问(如果您愿意)。