.NET 中的属性是什么?

发布于 2024-07-05 06:00:36 字数 40 浏览 9 评论 0原文

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

What are attributes in .NET, what are they good for, and how do I create my own attributes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

终遇你 2024-07-12 06:00:37

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

使用属性并了解其使用的适当场景是大部分工作。

As said, Attributes are relatively easy to create. The other part of the work is creating code that uses it. In most cases you will use reflection at runtime to alter behavior based on the presence of an attribute or its properties. There are also scenarios where you will inspect attributes on compiled code to do some sort of static analysis. For example, parameters might be marked as non-null and the analysis tool can use this as a hint.

Using the attributes and knowing the appropriate scenarios for their use is the bulk of the work.

习惯成性 2024-07-12 06:00:37

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

其想法是,在运行时某些其他类型/框架/工具将查询在属性中输入信息并据此采取行动。

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

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

Attributes are, essentially, bits of data you want to attach to your types (classes, methods, events, enums, etc.)

The idea is that at run time some other type/framework/tool will query your type for the information in the attribute and act upon it.

So, for example, Visual Studio can query the attributes on a 3rd party control to figure out which properties of the control should appear in the Properties pane at design time.

Attributes can also be used in Aspect Oriented Programming to inject/manipulate objects at run time based on the attributes that decorate them and add validation, logging, etc. to the objects without affecting the business logic of the object.

白色秋天 2024-07-12 06:00:37

您可以使用自定义属性作为在子类中定义标记值的简单方法,而无需为每个子类一遍又一遍地编写相同的代码。 我遇到了一个很好的 John Waters 的简洁示例,说明了如何定义并在您自己的代码中使用自定义属性。

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

You can use custom attributes as a simple way to define tag values in sub classes without having to write the same code over and over again for each subclass. I came across a nice concise example by John Waters of how to define and use custom attributes in your own code.

There is a tutorial at http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

撞了怀 2024-07-12 06:00:37

要开始创建属性,请打开 C# 源文件,输入 attribute 并按 [TAB]。 它将扩展为新属性的模板。

To get started creating an attribute, open a C# source file, type attribute and hit [TAB]. It will expand to a template for a new attribute.

夜未央樱花落 2024-07-12 06:00:37

属性也常用于面向方面的编程。 有关此示例,请查看 PostSharp 项目。

Attributes are also commonly used for Aspect Oriented Programming. For an example of this check out the PostSharp project.

旧伤还要旧人安 2024-07-12 06:00:37

在我目前正在进行的项目中,有一组各种风格的 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。 有一个列表框,用户可以将其拖放到页面上以创建控件的实例。 为了填充列表框,我获取控件的 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 是令人厌恶的,但这是我必须使用的:-( )

你可以在大多数东西上添加属性,并且有一系列预定义的属性。上面提到的编辑器还会在描述属性以及如何编辑它的属性

一旦您了解了整个想法,您就会想知道如果没有它们您将如何生活。

In the project I'm currently working on, there is a set of UI objects of various flavours and an editor to assembly these objects to create pages for use in the main application, a bit like the form designer in DevStudio. These objects exist in their own assembly and each object is a class derived from UserControl and has a custom attribute. This attribute is defined like this:

[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;
};

and I apply it to a class like this:

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

which is what the previous posters have said.

To use the attribute, the editor has a Generic::List <Type> containing the control types. There is a list box which the user can drag from and drop onto the page to create an instance of the control. To populate the list box, I get the ControlDescriptionAttribute for the control and fill out an entry in the list:

// 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;
  }
}

Note: the above is C++/CLI but it's not difficult to convert to C#
(yeah, I know, C++/CLI is an abomination but it's what I have to work with :-( )

You can put attributes on most things and there are whole range of predefined attributes. The editor mentioned above also looks for custom attributes on properties that describe the property and how to edit it.

Once you get the whole idea, you'll wonder how you ever lived without them.

孤独岁月 2024-07-12 06:00:36

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

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

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”,编译器将为您添加该后缀。

注意:属性本身不执行任何操作 - 需要有其他代码使用它们。 有时该代码是为您编写的,但有时您必须自己编写。 例如,C# 编译器关心某些框架,并且某些框架使用某些框架(例如,NUnit 在加载程序集时在类上查找 [TestFixture],在测试方法上查找 [Test])。
因此,在创建您自己的自定义属性时,请注意它根本不会影响代码的行为。 您需要编写检查属性(通过反射)并对其进行操作的其他部分。

Metadata. Data about your objects/methods/properties.

For example I might declare an Attribute called: DisplayOrder so I can easily control in what order properties should appear in the UI. I could then append it to a class and write some GUI components that extract the attributes and order the UI elements appropriately.

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;
        }
    }
}

Thereby ensuring that SomeInt is always displayed before SomeDate when working with my custom GUI components.

However, you'll see them most commonly used outside of the direct coding environment. For example the Windows Designer uses them extensively so it knows how to deal with custom made objects. Using the BrowsableAttribute like so:

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

Tells the designer not to list this in the available properties in the Properties window at design time for example.

You could also use them for code-generation, pre-compile operations (such as Post-Sharp) or run-time operations such as Reflection.Emit.
For example, you could write a bit of code for profiling that transparently wrapped every single call your code makes and times it. You could "opt-out" of the timing via an attribute that you place on particular methods.

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);
    }
}

Declaring them is easy, just make a class that inherits from Attribute.

public class DisplayOrderAttribute : Attribute
{
    private int order;

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

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

And remember that when you use the attribute you can omit the suffix "attribute" the compiler will add that for you.

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.

可遇━不可求 2024-07-12 06:00:36

很多人已经回答了,但到目前为止还没有人提到这一点......

属性大量使用反射。 反射已经相当慢了。

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

考虑在哪里适合使用此类属性也是一个好主意,并通过 AttributeUsage。 可用属性用法的列表可能会让您感到惊讶:

  • 程序集
  • 模块
  • 结构
  • 枚举
  • 构造函数
  • 方法
  • 属性
  • 字段 事件
  • 接口
  • 参数
  • 委托
  • ReturnValue
  • GenericParameter
  • All
  • AttributeUsage

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

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

Many people have answered but no one has mentioned this so far...

Attributes are used heavily with reflection. Reflection is already pretty slow.

It is very worthwhile marking your custom attributes as being sealed classes to improve their runtime performance.

It is also a good idea to consider where it would be appropriate to use place such an attribute, and to attribute your attribute (!) to indicate this via AttributeUsage. The list of available attribute usages might surprise you:

  • Assembly
  • Module
  • Class
  • Struct
  • Enum
  • Constructor
  • Method
  • Property
  • Field
  • Event
  • Interface
  • Parameter
  • Delegate
  • ReturnValue
  • GenericParameter
  • All

It's also cool that the AttributeUsage attribute is part of the AttributeUsage attribute's signature. Whoa for circular dependencies!

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
夜血缘 2024-07-12 06:00:36

属性是一种用于标记类的元数据。 例如,这通常在 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 其中有一个非常好的描述。
我希望这对您有所帮助!

Attributes are a kind of meta data for tagging classes. This is often used in WinForms for example to hide controls from the toolbar, but can be implemented in your own application to enable instances of different classes to behave in specific ways.

Start by creating an attribute:

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

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

All attribute classes must have the suffix "Attribute" to be valid.
After this is done, create a class that uses the attribute.

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

Now you can check a specific class' SortOrderAttribute (if it has one) by doing the following:

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;
        }
    }
}

If you want to read more about this you can always check out MSDN which has a pretty good description.
I hope this helped you out!

萌化 2024-07-12 06:00:36

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

至于它们的用途……它们的用途几乎是无限的。

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

An attribute is a class that contains some bit of functionality that you can apply to objects in your code. To create one, create a class that inherits from System.Attribute.

As for what they're good for... there are almost limitless uses for them.

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

路弥 2024-07-12 06:00:36

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

它们适用于许多事情(调试器可视化、将事物标记为过时、将事物标记为可序列化,列表是无穷无尽的)。

创建您自己的定制产品非常简单。 从这里开始:

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

Attributes are like metadata applied to classes, methods or assemblies.

They are good for any number of things (debugger visualization, marking things as obsolete, marking things as serializable, the list is endless).

Creating your own custom ones is easy as pie. Start here:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文