Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
    }
like image 740
Gareth D Avatar asked Oct 12 '09 11:10

Gareth D


People also ask

Is AttributeUsage inherited?

Attribute class is marked with [AttributeUsage(AttributeTargets. All, Inherited = true, AllowMultiple = false)] . Thus, any attribute class will inherit this attribute, unless you specify a different one.

Which of the following is an example of derived attribute?

Derived attribute : An attribute that can be derived from other attributes is derived attributes. Example: Total and average marks of a student.

What is derived attribute in DBMS?

A derived attribute is an attribute whose values are calculated from other attributes. In a student table if we have an attribute called as date_of_birth and age. We can derive value of age with the help of date_of_birth attribute.

What is AttributeUsage C#?

Determines how a custom attribute class can be used. AttributeUsage is an attribute that can be applied to custom attribute definitions to control how the new attribute can be applied. So it basically gives the compiler some extra information about the attribute class you will implement.


1 Answers

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

like image 143
Marc Gravell Avatar answered Nov 15 '22 08:11

Marc Gravell