在运行时修改类属性
我不确定我是否有可能看到:
在运行时更改Attribute的参数。
我的情况非常相似,但我试图在运行时更改类的属性:
[Category("Change me")] public class Classic { public string Name { get; set; } }
其中一个答案是:
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")
更改为更易阅读的格式,感谢Marc Gravell:
TypeDescriptor.AddAttributes(table, new Category{ Name = "Changed" });
使用TypeDescriptor时,一切都很好,但使用时:
var attrs = (Category[])typeof(Classic).GetCustomAttributes( typeof(Category), true); attrs[0].Name
名称包含“更改我”文本。
有没有办法在运行时更改此属性?
编辑:
我在设计器中为Linq2Sql需要这个,生成的代码具有DB模式。 我想使用用户的默认架构而不使用XML映射或更改生成的代码(表仍处于开发阶段并经常更改)。
设计师代码是:
[global::System.Data.Linq.Mapping.TableAttribute(Name="DbSchema.MyTable")] public partial class MyTable
我希望该属性为:
[TableAttribute(Name="MyTable")]
现在我已经挖掘了框架代码,我认为linq2sql使用:
TableAttribute[] attrs = (TableAttribute[])typeof(MyTable) .GetCustomAttributes(typeof(TableAttribute), true);
当我使用TypeDescriptor更改属性时,GetCustomAttributes中的值不会更改。
完全避免reflection,您可以通过TypeDescriptor
执行此操作:
using System; using System.ComponentModel; using System.Linq; [Category("nice")] class Foo { } static class Program { static void Main() { var ca = TypeDescriptor.GetAttributes(typeof(Foo)) .OfType().FirstOrDefault(); Console.WriteLine(ca.Category); // <=== nice TypeDescriptor.AddAttributes(typeof(Foo),new CategoryAttribute("naughty")); ca = TypeDescriptor.GetAttributes(typeof(Foo)) .OfType ().FirstOrDefault(); Console.WriteLine(ca.Category); // <=== naughty } }
如果你使用reflection ,那么不太像这样 – reflection属性不能被替换 – 只有组件模型视图受到TypeDescriptor
影响。 但是,您可以将CategoryAttribute
子类CategoryAttribute
您的目的。 特别适用于i18n。
using System.ComponentModel; using System; [MyCategory("Fred")] class Foo { } static class Program { static void Main() { var ca = (CategoryAttribute)Attribute.GetCustomAttribute(typeof(Foo), typeof(CategoryAttribute)); Console.WriteLine(ca.Category); // ^^^ writes "I was Fred, but not I'm EVIL Fred" } } class MyCategoryAttribute : CategoryAttribute { public MyCategoryAttribute(string category) : base(category) { } protected override string GetLocalizedString(string value) { return "I was " + value + ", but not I'm EVIL " + value; } }
您需要对属性进行编码,以便它支持运行时值。 例如,validation属性通过设置资源类型和资源字符串而不是静态消息字符串来支持消息的国际化。
另一种方法是使用诸如StructureMap或Unity的IOC容器来提供一些提供值的对象/服务。
如果您不想将属性耦合到特定容器,请使用Patterns and Practices组提供的Common ServiceLocator包装器。