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
}
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.
Derived attribute : An attribute that can be derived from other attributes is derived attributes. Example: Total and average marks of a student.
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.
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.
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]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With