2008-09-24 101 views

回答

63

属性是静态元数据。组件,模块,类型,成员,参数和返回值不是C#中的第一类对象(例如,System.Type类仅仅是类型的反映表示)。您可以获取某个类型的属性实例,并在属性可写的情况下更改这些属性,但不会影响该属性应用于此类型。

3

我不这么认为。即使我错了,你所希望的最好的结果就是将它们添加到整个类型中,而不是类型的实例

+21

TypeDescriptor.AddAttributes(Object,Attribute [])将类级属性添加到目标组件实例。 – 2008-11-10 12:25:46

4

不,不是。

属性是元数据,并以二进制形式存储在已编译的程序集中(这也是为什么您只能在其中使用简单类型)。

9

你不能。一种解决方法可能是在运行时生成派生类并添加属性,但这可能有点矫枉过正。

3

如果你需要能够动态添加的东西,c#属性不是这样。看看将数据存储在xml中。我最近做了一个项目,我开始w /属性,但最终移动到序列化w/xml。

3

为什么你需要?属性为反射提供了额外的信息,但是如果你从外部知道你想要的属性,则不需要它们。

您可以在外部相对容易地将元数据存储在数据库或资源文件中。

+1

消除锅炉板。如果您可以让类根据类中的代码自动生成属性,那不是很方便吗?我试图找出这样的东西来减少SQL CLR对象中的样板。在其他语言中很容易......见http://www.paulgraham.com/avg.html – 2011-05-31 01:30:52

65

这实际上取决于你想要完成什么。

System.ComponentModel.TypeDescriptor东西可以用来为类型,属性和对象实例添加属性,它也有限制,你必须使用它来检索这些属性。如果你正在编写使用这些属性的代码,并且你可以在这些限制之内生活,那么我肯定会建议它。

据我所知,PropertyGrid控件和Visual Studio设计界面是BCL中唯一使用TypeDescriptor的东西。事实上,这就是他们如何处理他们真正需要做的一半事情。

+5

实际上,大多数数据绑定使用“TypeDescriptor” - 而不仅仅是“PropertyGrid”。 – 2010-09-09 05:23:16

+1

任何解决方法在Silverlight项目中添加属性元数据属性(其中“TypeDescriptor”和“TypeDescriptionProvider”未实现? – Shimmy 2012-02-25 22:01:21

+0

重要提示:TypeDescriptor.GetAttributes()不处理重复属性,它只选择最后一个只有`Attr(3)` – ohmusama 2013-05-22 17:45:58

0

我很努力有没有成功System.ComponentModel.TypeDescriptor。这并不意味着它不能工作,但我希望看到代码。

在柜台部分,我想改变一些属性值。 我做了2个功能,为此目的正常工作。

 // ************************************************************************ 
     public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName, string description) 
     { 
      PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName]; 
      var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute; 
      if (att != null) 
      { 
       var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance); 
       if (fieldDescription != null) 
       { 
        fieldDescription.SetValue(att, description); 
       } 
      } 
     } 

     // ************************************************************************ 
     public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly) 
     { 
      PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName]; 
      var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute; 
      if (att != null) 
      { 
       var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance); 
       if (fieldDescription != null) 
       { 
        fieldDescription.SetValue(att, isReadOnly); 
       } 
      } 
     }