.NET中的属性是什么,它们有什么好处,我如何创建自己的属性?


属性是一个类,它包含一些可以应用于代码中的对象的功能。要创建一个类,请创建一个继承自System.Attribute的类。

至于它们有什么好处……它们的用途几乎是无限的。

http://www.codeproject.com/KB/cs/dotnetattributes.aspx


属性就像应用于类、方法或程序集的元数据。

它们适用于任何数量的事情(调试器可视化,标记为过时的东西,标记为可序列化的东西,列表是无限的)。

创建您自己的自定义是很容易的。从这里开始:

http://msdn.microsoft.com/en-us/library/sw480ze8 (VS.71) . aspx


您可以使用自定义属性作为在子类中定义标记值的简单方法,而不必为每个子类反复编写相同的代码。我看到John Waters写的一个很好的简洁示例,介绍了如何在自己的代码中定义和使用自定义属性。

在http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx上有一个教程


元数据。关于对象/方法/属性的数据。

例如,我可以声明一个名为:DisplayOrder的属性,这样我就可以很容易地控制属性应该在UI中出现的顺序。然后,我可以将它附加到一个类中,并编写一些提取属性并对UI元素进行适当排序的GUI组件。

public class DisplayWrapper
{
    private UnderlyingClass underlyingObject;

    public DisplayWrapper(UnderlyingClass u)
    {
        underlyingObject = u;
    }

    [DisplayOrder(1)]
    public int SomeInt
    {
        get
        {
            return underlyingObject .SomeInt;
        }
    }

    [DisplayOrder(2)]
    public DateTime SomeDate
    {
        get
        {
            return underlyingObject .SomeDate;
        }
    }
}

因此,在使用自定义GUI组件时,确保SomeInt始终显示在SomeDate之前。

但是,您将看到它们最常用于直接编码环境之外。例如,Windows设计器广泛使用它们,因此它知道如何处理自定义对象。像这样使用BrowsableAttribute:

[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
    get{/*do something*/}
}

例如,告诉设计器在设计时不要在“属性”窗口的可用属性中列出此属性。

您还可以将它们用于代码生成、预编译操作(如Post-Sharp)或运行时操作(如Reflection.Emit)。 例如,您可以编写一些用于分析的代码,透明地包装代码所做的每个调用并计时。你可以通过设置在特定方法上的属性来“退出”计时。

public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
    bool time = true;
    foreach (Attribute a in target.GetCustomAttributes())
    {
        if (a.GetType() is NoTimingAttribute)
        {
            time = false;
            break;
        }
    }
    if (time)
    {
        StopWatch stopWatch = new StopWatch();
        stopWatch.Start();
        targetMethod.Invoke(target, args);
        stopWatch.Stop();
        HandleTimingOutput(targetMethod, stopWatch.Duration);
    }
    else
    {
        targetMethod.Invoke(target, args);
    }
}

声明它们很简单,只需创建一个从Attribute继承的类。

public class DisplayOrderAttribute : Attribute
{
    private int order;

    public DisplayOrderAttribute(int order)
    {
        this.order = order;
    }

    public int Order
    {
        get { return order; }
    }
}

记住,当你使用属性时,你可以省略后缀“attribute”,编译器会为你添加。

NOTE: Attributes don't do anything by themselves - there needs to be some other code that uses them. Sometimes that code has been written for you but sometimes you have to write it yourself. For example, the C# compiler cares about some and certain frameworks frameworks use some (e.g. NUnit looks for [TestFixture] on a class and [Test] on a test method when loading an assembly). So when creating your own custom attribute be aware that it will not impact the behaviour of your code at all. You'll need to write the other part that checks attributes (via reflection) and act on them.


属性是一种标记类的元数据。这通常用于WinForms中,例如在工具栏中隐藏控件,但可以在您自己的应用程序中实现,以使不同类的实例以特定的方式运行。

首先创建一个属性:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
    public int SortOrder { get; set; }

    public SortOrderAttribute(int sortOrder)
    {
        this.SortOrder = sortOrder;
    }
}

所有属性类必须有后缀“attribute”才有效。 完成此操作后,创建一个使用该属性的类。

[SortOrder(23)]
public class MyClass
{
    public MyClass()
    {
    }
}

现在你可以检查一个特定类的SortOrderAttribute(如果它有的话),方法如下:

public class MyInvestigatorClass
{
    public void InvestigateTheAttribute()
    {
        // Get the type object for the class that is using
        // the attribute.
        Type type = typeof(MyClass);

        // Get all custom attributes for the type.
        object[] attributes = type.GetCustomAttributes(
            typeof(SortOrderAttribute), true);

        // Now let's make sure that we got at least one attribute.
        if (attributes != null && attributes.Length > 0)
        {
            // Get the first attribute in the list of custom attributes
            // that is of the type "SortOrderAttribute". This should only
            // be one since we said "AllowMultiple=false".
            SortOrderAttribute attribute = 
                attributes[0] as SortOrderAttribute;

            // Now we can get the sort order for the class "MyClass".
            int sortOrder = attribute.SortOrder;
        }
    }
}

如果你想了解更多这方面的信息,你可以查看MSDN,那里有很好的描述。 我希望这对你有所帮助!


如前所述,属性相对容易创建。工作的另一部分是创建使用它的代码。在大多数情况下,您将在运行时使用反射来根据属性或其属性的存在来改变行为。在某些情况下,您将检查已编译代码上的属性以进行某种静态分析。例如,参数可能被标记为非空,分析工具可以将此作为提示。

使用这些属性并了解使用它们的适当场景是大部分工作。


在我目前从事的项目中,有一组不同风格的UI对象和一个编辑器来组装这些对象以创建用于主应用程序的页面,有点像DevStudio中的表单设计器。这些对象存在于它们自己的程序集中,每个对象都是从UserControl派生的类,并具有自定义属性。该属性的定义如下:

[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
  ControlDescriptionAttribute (String ^name, String ^description) :
    _name (name),
    _description (description)
  {
  }

  property String ^Name
  {
    String ^get () { return _name; }
  }

  property String ^Description
  {
    String ^get () { return _description; }
  }

private:
  String
    ^ _name,
    ^ _description;
};

我把它应用到这样一个课上:

[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
  // stuff
};

之前的海报也是这么说的。

要使用该属性,编辑器有一个Generic::List <Type>,其中包含控件类型。有一个列表框,用户可以从该列表框中拖放到该页上,以创建控件的实例。为了填充列表框,我获得控件的ControlDescriptionAttribute,并在列表中填写一个条目:

// done for each control type
array <Object ^>
  // get all the custom attributes
  ^attributes = controltype->GetCustomAttributes (true);

Type
  // this is the one we're interested in
  ^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;

// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
  if (attributetype->IsInstanceOfType (attribute))
  {
    ECMMainPageDisplay::ControlDescriptionAttribute
      ^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);

    // get the name and description and create an entry in the list
    ListViewItem
      ^item = gcnew ListViewItem (description->Name);

    item->Tag = controltype->Name;
    item->SubItems->Add (description->Description);

    mcontrols->Items->Add (item);
    break;
  }
}

注:上面是c++ /CLI,但是转换成c#并不难 (是的,我知道,c++ /CLI是一个讨厌的东西,但它是我必须使用的:-()

你可以把属性放在大多数东西上,有一整套预定义的属性。上面提到的编辑器还会在描述属性以及如何编辑属性的属性上查找自定义属性。

一旦你明白了它们的全部含义,你就会想,没有它们你是怎么生活的。


本质上,属性是您想要附加到类型(类、方法、事件、枚举等)的数据位。

其思想是,在运行时,一些其他类型/框架/工具将在属性中查询您的类型的信息并对其进行操作。

因此,例如,Visual Studio可以查询第三方控件上的属性,以确定控件的哪些属性应该在设计时出现在“属性”窗格中。

属性还可以在面向方面编程中使用,在运行时根据装饰它们的属性注入/操作对象,并向对象添加验证、日志记录等,而不影响对象的业务逻辑。


要开始创建一个属性,打开一个c#源文件,输入attribute并点击[TAB]。它将展开为一个新属性的模板。


很多人都回答了,但到目前为止还没有人提到这个问题……

属性与反射一起被大量使用。反射已经相当慢了。

将自定义属性标记为密封类以提高其运行时性能是非常值得的。

考虑在哪里使用place这样的属性是合适的,并通过AttributeUsage来指定属性(!),这也是一个好主意。可用属性用法的列表可能会让你大吃一惊:

组装 模块 类 结构体 枚举 构造函数 方法 财产 场 事件 接口 参数 委托 ReturnValue GenericParameter 所有

AttributeUsage属性是AttributeUsage属性签名的一部分,这也很酷。哇,循环依赖!

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute

属性也通常用于面向方面编程。要获得这样的示例,请查看PostSharp项目。