C#: 如何在运行时向对象添加属性?

11
作为一个实体类,我想在运行时添加一个属性,应该怎么做?
7个回答

11

需要查看哪些属性?如果是像数据绑定等的东西,TypeDescriptor 应该可以解决:

TypeDescriptor.AddAttributes(type, attribs);
TypeDescriptor.AddAttributes(instance, attribs);

这仅影响System.ComponentModel的使用(而不是直接反射),但通常足够了 - 例如,您可以通过上述方式关联TypeConverter

如果你所说的 "attributes" 指的是 "properties",那么(就数据绑定而言)TypeDescriptor 在这方面也有潜力 - 但它并不容易;您需要在对象上实现 ICustomTypeDescriptor,或者为该类型编写一个 CustomTypeDescriptor - 无论哪种情况,您都需要编写自己的 PropertyDescriptor 实现(通常需要与每个实例的字典进行交互等)。 这将被任何使用以下内容的东西使用:

// only works if you use TypeDescriptionProvider
PropertyDescriptorCollection typeProps = TypeDescriptor.GetProperties(type);
// works via TypeDescriptionProvider or ICustomTypeDescriptor
PropertyDescriptorCollection objProps = TypeDescriptor.GetProperties(obj);

再次说明,这涵盖了各种数据绑定和类似场景。关于此的一个例子,请参见此处 - 然而,这远非易事。该链接中的示例用法在运行时添加了两个属性:

Bag.AddProperty<int>("TestProp", new DefaultValueAttribute(5)); 
Bag.AddProperty<string>("Name"); 

2
编辑:请澄清一下,您是在谈论 c#属性 还是类中的成员?
您唯一能够添加 c# 属性的方法是生成一个带有额外属性的全新类,编译并加载新程序集到现有的 AppDomain 中。

他所说的“类”,是指一个全新的类型,而不仅仅是同一类的另一个实例。 - Joel Coehoorn
@Joel非常正确,我可以看出这可能有点模棱两可。谢谢。 - Rex M

1

使用哈希表来存储你的属性。

如果你想要更多的运行时灵活性,可以尝试使用Ruby或其他解释型语言。


Ruby、PHP和Python是动态语言。C#、Java和VB是静态语言。将interpreted替换为dynamic。 - strager
当然,说得对。任何语言都可以编译,也可以解释执行。只是有趣的巧合是,Ruby、PHP和Python通常是解释执行的,而C#、Java和VB则是编译的... - Bill K
我见过编译的Python。而VB以前是解释执行的(制作EXE会将代码嵌入exe文件中并附带解释器)。 - configurator
是的,编译与非编译并不是一个非常有趣的区分。我的错。 - Bill K

1

属性是类型的元数据的一部分,因此它们在编译后的程序集中被硬编码(这也是为什么您只能使用某些基本类型而不能在属性中使用任意数据的原因)。

结果是您无法在运行时向类型添加任何属性。但是有各种替代技术。您可以使用简单的字典或更强大的附加依赖属性之类的东西。


0

0

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接