在运行时更改Attribute的参数

Gra*_*ton 65 c# reflection attributes

我不确定是否可以在运行时更改属性的参数?例如,在程序集内部,我有以下类

public class UserInfo
{
    [Category("change me!")]
    public int Age
    {
        get;
        set;
    }
    [Category("change me!")]
    public string Name
    {
        get;
        set;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是由第三方供应商提供的类,我无法更改代码.但是现在我发现上面的描述并不准确,并且当我将上述类的实例绑定到属性网格时,我想将"更改我"类别名称更改为其他名称.

我可以知道怎么做吗?

Gle*_*ven 27

那么你每天都学到新的东西,显然我撒了谎:

通常没有意识到的是,您可以在运行时相当容易地更改属性实例值.当然,原因是创建的属性类的实例是完全正常的对象,可以不受限制地使用.例如,我们可以得到对象:

ASCII[] attrs1=(ASCII[])
    typeof(MyClass).GetCustomAttributes(typeof(ASCII), false);
Run Code Online (Sandbox Code Playgroud)

...更改其公共变量的值并显示它已更改:

attrs1[0].MyData="A New String";
MessageBox.Show(attrs1[0].MyData);
Run Code Online (Sandbox Code Playgroud)

...最后创建另一个实例并显示其值未更改:

ASCII[] attrs3=(ASCII[])
    typeof(MyClass).GetCustomAttributes(typeof(ASCII), false);
 MessageBox.Show(attrs3[0].MyData);
Run Code Online (Sandbox Code Playgroud)

http://www.vsj.co.uk/articles/display.asp?id=713

  • 好吧,不是真的.您可以创建属性对象的实例并对其进行修改,但它不会影响使用属性上标记的属性的任何内容(因为它们将获得自己未更改的实例). (13认同)

Jul*_*les 7

如果其他人沿着这条大道走下去,答案就是你可以用反射来做,除非你不能,因为框架中有一个错误.这是你如何做到的:

Dim prop As PropertyDescriptor = TypeDescriptor.GetProperties(GetType(UserInfo))("Age")
Dim att As CategoryAttribute = DirectCast(prop.Attributes(GetType(CategoryAttribute)), CategoryAttribute)
Dim cat As FieldInfo = att.GetType.GetField("categoryValue", BindingFlags.NonPublic Or BindingFlags.Instance)
cat.SetValue(att, "A better description")
Run Code Online (Sandbox Code Playgroud)

一切都很好,除了为所有属性更改了category属性,而不仅仅是'Age'.

  • 如果你在"BindingFlags.NonPublic"字段中干涉,我几乎不会把它称为bug. (4认同)
  • 我相信这确实是一个错误,因为即使您不使用“BindingFlags.NonPublic”字段,它也会发生在公共属性上。有谁知道这个问题是否已被提出?错误页面的链接会很有用。使用 TypeDescriptor 而不是 Reflection 效果非常好! (2认同)

Gle*_*ven 0

我真的不这么认为,除非有一些时髦的反思可以实现这一目标。属性装饰是在编译时设置的,据我所知是固定的