开发者

How can I set the value of a property on a attribute on a object?

开发者 https://www.devze.com 2023-03-23 22:41 出处:网络
I am trying 开发者_开发问答to set the value of a property on an attribute on a class. [FooAttr(ThePropertyIWantToSet=null)]

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(...).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号