I am trying 开发者_开发问答to set the value of a property on an attribute on a class.
[FooAttr(ThePropertyIWantToSet=null)]
public class Foo
{
}
Foo theFoo = new Foo();
theFoo.SetAttributeProperty<FooAttrAttribute>("ThePropertyIWantToSet", theValueIWantToSet);
This is the SetAttributeProperty extension method I have written. It compiles and runs but it doesn't seem to be setting the property.
public static void SetAttributeProperty<T>(this object instance, string fieldName, object value) where T : Attribute
{
var attr = instance.GetType().GetCustomAttributes(typeof (T), false).FirstOrDefault();
PropertyInfo pi = attr.GetType().GetProperty(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
pi.SetValue(attr, value, null);
}
Any ideas what I might be missing?
I've no idea whether this is even possible, but it's not how attributes are meant to be used. I don't know that there are any guarantees around how and when attribute instances are created. For example, it's quite possible that each time you ask a type or member for its attributes, they're deserialized from the metadata again.
Basically I think you should treat attributes as immutable after compilation, even if they have properties with setters.
EDIT: This short but complete program seems to indicate that Type.GetCustomAttributes
can indeed create a new instance each time you call it:
using System;
using System.Runtime.CompilerServices;
[AttributeUsageAttribute(AttributeTargets.All)]
class FooAttribute : Attribute
{
}
[Foo]
class Bar
{
}
class Program
{
static void Main(string[] args)
{
var attr = typeof(Bar).GetCustomAttributes(typeof(FooAttribute), true)[0];
var attr2 = typeof(Bar).GetCustomAttributes(typeof(FooAttribute), true)[0];
Console.WriteLine(attr == attr2); // Prints False
}
}
The only way to do that at runtime is to model attributes at runtime rather than reflection. Luckily TypeDescriptor
does this already. So you should find that if you only use TypeDescriptor
to get the attribute, then TypeDescriptor.AddAttributes(...)
should do the job of assigning a new attribute at runtime;
TypeDescriptor.AddAttributes(typeof(TargetType),
new Attribute[] {yourAttribWithNewValue});
However, this only works if the code consuming the attribute uses TypeDescriptor.GetAttributes(...)
.
精彩评论