C# 属性特性

15

我看到了以下代码:

[DefaultValue(100)]
[Description("Some descriptive field here")]
public int MyProperty{...} 

从上面的片段来看,其功能似乎已经很清晰了,但我不知道如何利用它来做有用的事情。我甚至不确定该给它什么名称!

有人知道在哪里可以找到更多关于这些属性特性的信息/教程吗?我也对此功能能够完成的任何新颖/有用任务感兴趣。

6个回答

27

从上面的片段中,功能似乎很清楚

但实际上,很多人认为[DefaultValue()] 设置 属性的值。其实它只是告诉一些视觉设计器(如Visual Studio),代码将把默认值设为什么。这样它就知道如果属性被设置为其他值,则在属性窗口中将其加粗显示。


那么如果我没有显式地将MyProperty设置为另一个值,表单设计器(或等效工具)会在幕后将MyProperty设置为100? - TK.
3
如果您不明确设置MyProperty的值,它将默认为0(假设有一个后备存储)。表单设计器将以“0”为值显示,但加粗显示,以暗示它已手动从默认值更改。这仅影响表单设计器中该值的外观。 - James Curran

13

人们已经涵盖了UI方面 - 属性还有其他用途,例如它们在大多数序列化框架中被广泛使用。

一些属性被编译器赋予特殊处理 - 例如,[PrincipalPermission(...)] 将声明性安全性添加到方法中,允许您(自动)检查用户是否具有适当的访问权限。

要添加自己的特殊处理,可以使用PostSharp;有许多很好的示例,可用PostSharp来执行AOP操作,如记录日志 - 或者只是代码简化,比如使用自动实现INotifyPropertyChanged


7
他们被称为属性,在 MSDN 上有很多相关信息,例如:http://msdn.microsoft.com/en-us/library/z0w1kczw.aspx
一般来说,它们本身不会“做”任何事情,而是被某些其他代码使用,这些代码将使用您的类。XmlSerialization 是一个很好的例子:XmlSerializer(作为框架的一部分由 Microsoft 提供)可以序列化几乎任何类(但类上有一些要求)- 它使用反射查看类中包含的数据。您可以使用属性(与 XmlSerializer 一起定义)来更改 XmlSerializer 序列化您的类的方式(例如,告诉它将数据保存为属性而不是元素)。

6

你举的例子是由视觉设计师(例如MS Expression Blend和Visual Studio Designer)在设计UI时使用的,以提供提示。

请注意,它们是元数据,不会影响属性逻辑。例如设置DefaultValue不会默认将属性设置为该值,您必须手动设置。

如果出于某种原因您想要访问这些属性,您需要使用反射

有关设计师属性的更多信息,请参见MSDN


它们也被用于Visual Studio设计器中。 - Joel Coehoorn
需要注意的是,它们只是提示:例如,在代码中仍然需要将MyProperty的默认值设置为100,否则您会欺骗属性的使用者。 - Joel Coehoorn

3
我们使用它来定义应该加载哪个图形化设计师来配置特定类型的实例。
也就是说,我们有一种工作流设计师,它从程序集中加载所有可能的命令类型。这些命令类型具有需要配置的属性,因此每个命令类型都需要不同的设计师(用户控件)。
例如,考虑以下命令类型(在我们的解决方案中称为复合类型)。
[CompositeMetaData("Delay","Sets the delay between commands",1)]
[CompositeDesigner(typeof(DelayCompositeDesigner))]
public class DelayComposite : CompositeBase 
{
       // code here
}

这些信息用于两个地方:

1) 当设计师创建命令列表时,使用CompositeMetaData显示有关命令的更多信息。

2) 当用户向设计师添加命令并且设计师创建该类的实例时,它查看CompositeDesigner属性,创建指定类型(usercontrol)的新实例,并将其添加到可视化设计器中。

考虑以下代码,我们用它来加载命令到我们的“工具栏”中:

foreach (Type t in assembly.GetExportedTypes())  
{
    Console.WriteLine(t.Name);

    if (t.Name.EndsWith("Composite"))
    {
        var attributes = t.GetCustomAttributes(false);
        ToolboxListItem item = new ToolboxListItem();

        CompositeMetaDataAttribute meta = (CompositeMetaDataAttribute)attributes
                              .Where(a => a.GetType() == typeof(Vialis.LightLink.Attributes.CompositeMetaDataAttribute)).First();
        item.Name = meta.DisplayName;
        item.Description = meta.Description;
        item.Length = meta.Length;
        item.CompositType = t;

        this.lstCommands.Items.Add(item);
    }                           
}

正如您所看到的,对于程序集中名称以“Composite”结尾的每种类型, 我们获取自定义属性并使用该信息填充ToolboxListItem实例。

至于加载设计师,可以这样检索属性:

var designerAttribute = (CompositeDesignerAttribute)item.CompositType.GetCustomAttributes(false)
                         .Where(a => a.GetType() == typeof(CompositeDesignerAttribute)).FirstOrDefault();

这只是一个例子,展示了你如何使用自定义属性。希望这能给你一个起点。

2

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