views:

80

answers:

1

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
    }
+2  A: 

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].

Marc Gravell
I feared that might be the case, thanks for the confirmation.
Gareth D