Я понимаю, что это время компиляции, поэтому они не могут быть общими и должны быть инициализированы постоянными значениями. Но:
Почему они не могут получить информацию, которую вы получили бы, если бы вы отражали то, к чему они применяются?
Почему они не могут принимать лямбда-выражения, функции или делегаты? Не являются ли функции постоянными для компилятора?
Атрибуты могли бы быть феноменально мощным декларативным инструментом, если бы только одно из вышеперечисленного было верным, вместо этого они больше походили на комментарии, которые можно было прочитать через отражение.
Это было что-то напыщенное, но я действительно хочу знать, почему они кажутся такими недоделанными.
Вот что я хотел сделать. Предполагалось, что это API для сопоставления значений из ресурсов через функцию, присвоенную атрибуту свойству, к которому применяется атрибут. Обратите внимание, что абстрактный класс не должен был бы существовать, если бы атрибуты могли знать, что они отражают. Я публикую это, потому что кто-то хотел знать, почему я хотел бы дать функции конструкторам атрибутов, и, возможно, потому, что то, что я пытаюсь сделать, уже сделано.
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)
{
}
}