I understand that they are compile time, so they can’t be generic, and must be initialized with constant values. But:
Why can’t they have information you would get if you reflected whatever they are being applied to?
Why can’t they accept lambda expressions, functions, or delegates? Aren’t functions constant to the compiler?
Attributes could be a phenomenally powerful declarative tool if just one of the above were true, instead they are more like comments that can be read through reflection.
This was sort of a rant, but I really want to know why they seem like such a half assed feature.
Here is what I wanted to do. It was supposed to be an api for mapping values from resources through the function given to the attribute to the property the attribute is applied to. Note that the abstract class wouldn’t have to exist if Attributes could know what they are reflecting. I’m posting this because someone wanted to know why I would want to give functions to attribute constructors, and maybe because what I’m trying to do has already been done.
public delegate void PropertyHandler(object parent, PropertyInfo property, object value);
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class FromResourceAttribute : Attribute
{
private static readonly PropertyHandler m_defaultHandler = (parent, property, value) =>
{
property.SetValue(parent, value, null);
};
public PropertyHandler Handler { get; set; }
public FromResourceAttribute(PropertyHandler handler)
{
Handler = handler;
}
public FromResourceAttribute()
{
Handler = m_defaultHandler;
}
}
public abstract class ResourceDependent
{
public ResourceDependent(ResourceManager resources)
{
var resourceDependentProperties =
from property in GetType().GetProperties()
let fromResourceAttributes = property.GetCustomAttributes(typeof(FromResourceAttribute), true)
where fromResourceAttributes.Count() == 1
let propertyHandler = ((FromResourceAttribute)fromResourceAttributes.Single()).Handler
select new { Info = property, Handler = propertyHandler };
foreach(var property in resourceDependentProperties)
{
property.Handler(this, property.Info, resources.GetObject(property.Info.Name));
}
}
}
class ResourceDependentTest : ResourceDependent
{
[FromResource]
public string Data { get; set; }
[FromResource((parent, property, value) => property.SetValue(parent, ((string)value).Split('|'), null))]
public string[] Data2 { get; set; }
static PropertyHandler Data3Handler = (parent, property, value) =>
{
//Magic
};
[FromResource(Data3Handler)]
public int Data3 { get; set; }
public ResourceDependentTest() : base(Properties.Resources.ResourceManager)
{
}
}
Why can’t they have information you would get if you reflected whatever they are being applied to?
Part of the reason is attributes don’t have to be applied to anything. It’s perfectly legal to new up an attribute in imperative code which is not attached to anything.
Why can’t they accept lambda expressions, functions, or delegates? Aren’t functions constant to the compiler?
All of these resolve down to the question of why delegates cannot be a part of an attribute. At their core delegates are made up of two parts 1) an instance and 2) a pointer to a method. #1 pretty much kills it as the instance is not constant and can’t be a part of the attribute value.
There are several other case which exist with delegates including delegate’s to static methods and expression trees. These have similar issues though in that all parts of the expression are not constant hence not encodable in an attribute value.