What are attributes in .NET?

2019-01-01 04:44发布

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

11条回答
若你有天会懂
2楼-- · 2019-01-01 05:05

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

查看更多
只靠听说
3楼-- · 2019-01-01 05:07

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.

查看更多
琉璃瓶的回忆
4楼-- · 2019-01-01 05:14

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.

查看更多
人间绝色
5楼-- · 2019-01-01 05:15

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!

查看更多
栀子花@的思念
6楼-- · 2019-01-01 05:20

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.

查看更多
后来的你喜欢了谁
7楼-- · 2019-01-01 05:22

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
查看更多
登录 后发表回答