Search code examples
c#inheritanceattributesallowmultiple

Honouring of AttributeUsage on derived attribute types


Given the following, I would not expect the compiler to allow multiple attributes that are derived from the base attribute, given that is set to AllowMultiple=false. In fact it compiles without a problem - what am I missing here?

using System;

[AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=true)]
abstract class BaseAttribute : Attribute { }

sealed class DerivedAttributeA : BaseAttribute { }

sealed class DerivedAttributeB : BaseAttribute { }

    class Sample1
    {
        [DerivedAttributeA()]
        [DerivedAttributeB()]
        public string PropertyA{ get; set; } // allowed, concrete classes differ

        [DerivedAttributeA()]
        [DerivedAttributeA()]
        public string PropertyB { get; set; } // not allowed, concrete classes the same, honours AllowMultiple=false on BaseAttribute
    }

Solution

  • The problem is simply that the AllowMultiple check only compares attributes of the same actual type (i.e. the concrete type instantiated) - and is perhaps best used with sealed attributes for this reason.

    It will, for example, enforce the following (as an illegal duplicate), inheriting this from BaseAttribute:

    [DerivedAttributeB()]
    [DerivedAttributeB()]
    public string Name { get; set; }
    

    In short, I don't think you can do what you want here... (enforce no more than one instance including subclasses of BaseAttribute per property).

    A similar example of this problem would be:

    [Description("abc")]
    [I18NDescriptionAttribute("abc")]
    public string Name { get; set; }
    
    class I18NDescriptionAttribute : DescriptionAttribute {
        public I18NDescriptionAttribute(string resxKey) : base(resxKey) { } 
    }
    

    The intent above is to provide a [Description] from resx at runtime (fully supported by ComponentModel etc) - but it can't stop you also adding a [Description].