C# Add custom attribute to a class without modify [duplicate] - c#

Is it possible to add attributes at runtime or to change the value of an attribute at runtime?

This really depends on what exactly you're trying to accomplish.
The System.ComponentModel.TypeDescriptor stuff can be used to add attributes to types, properties and object instances, and it has the limitation that you have to use it to retrieve those properties as well. If you're writing the code that consumes those attributes, and you can live within those limitations, then I'd definitely suggest it.
As far as I know, the PropertyGrid control and the visual studio design surface are the only things in the BCL that consume the TypeDescriptor stuff. In fact, that's how they do about half the things they really need to do.

Attributes are static metadata. Assemblies, modules, types, members, parameters, and return values aren't first-class objects in C# (e.g., the System.Type class is merely a reflected representation of a type). You can get an instance of an attribute for a type and change the properties if they're writable but that won't affect the attribute as it is applied to the type.

You can't. One workaround might be to generate a derived class at runtime and adding the attribute, although this is probably bit of an overkill.

Well, just to be different, I found an article that references using Reflection.Emit to do so.
Here's the link: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , you will also want to look into some of the comments at the bottom of the article, because possible approaches are discussed.

No, it's not.
Attributes are meta-data and stored in binary-form in the compiled assembly (that's also why you can only use simple types in them).

I don't believe so. Even if I'm wrong, the best you can hope for is adding them to an entire Type, never an instance of a Type.

If you need something to be able to added dynamically, c# attributes aren't the way. Look into storing the data in xml. I recently did a project that i started w/ attributes, but eventually moved to serialization w/ xml.

Why do you need to? Attributes give extra information for reflection, but if you externally know which properties you want you don't need them.
You could store meta data externally relatively easily in a database or resource file.

Like mentionned in a comment below by Deczaloth, I think that metadata is fixed at compile time. I achieve it by creating a dynamic object where I override GetType() or use GetCustomType() and writing my own type. Using this then you could...
I tried very hard with System.ComponentModel.TypeDescriptor without success. That does not means it can't work but I would like to see code for that.
In counter part, I wanted to change some Attribute values.
I did 2 functions which work fine for that purpose.
// ************************************************************************
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);
}
}
}

When faced with this situation, yet another solution might be questioning you code design and search for a more object-oriented way. For me, struggling with unpleasant reflection work arounds is the last resort. And my first reaction to this situation would be re-designing the code. Think of the following code, which tries to solve the problem that you have to add an attribute to a third-party class you are using.
class Employee {} // This one is third-party.
And you have code like
var specialEmployee = new Employee();
// Here you need an employee with a special behaviour and want to add an attribute to the employee but you cannot.
The solution might be extracting a class inheriting from the Employee class and decorating it with your attribute:
[SpecialAttribute]
class SpecialEmployee : Employee
{
}
When you create an instance of this new class
var specialEmployee = new SpecialEmployee();
you can distinguish this specialEmployee object from other employee objects. If appropriate, you may want to make this SpecialEmployee a private nested class.

Related

How the meta tags of a method work? [duplicate]

What are attributes in .NET, what are they good for, and how do I create my own attributes?
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.
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
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!
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
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
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.
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.
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.
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
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.
Attributes are also commonly used for Aspect Oriented Programming. For an example of this check out the PostSharp project.

Is it possible to add attributes to an existing class using .NET reflection? [duplicate]

Is it possible to add attributes at runtime or to change the value of an attribute at runtime?
This really depends on what exactly you're trying to accomplish.
The System.ComponentModel.TypeDescriptor stuff can be used to add attributes to types, properties and object instances, and it has the limitation that you have to use it to retrieve those properties as well. If you're writing the code that consumes those attributes, and you can live within those limitations, then I'd definitely suggest it.
As far as I know, the PropertyGrid control and the visual studio design surface are the only things in the BCL that consume the TypeDescriptor stuff. In fact, that's how they do about half the things they really need to do.
Attributes are static metadata. Assemblies, modules, types, members, parameters, and return values aren't first-class objects in C# (e.g., the System.Type class is merely a reflected representation of a type). You can get an instance of an attribute for a type and change the properties if they're writable but that won't affect the attribute as it is applied to the type.
You can't. One workaround might be to generate a derived class at runtime and adding the attribute, although this is probably bit of an overkill.
Well, just to be different, I found an article that references using Reflection.Emit to do so.
Here's the link: http://www.codeproject.com/KB/cs/dotnetattributes.aspx , you will also want to look into some of the comments at the bottom of the article, because possible approaches are discussed.
No, it's not.
Attributes are meta-data and stored in binary-form in the compiled assembly (that's also why you can only use simple types in them).
I don't believe so. Even if I'm wrong, the best you can hope for is adding them to an entire Type, never an instance of a Type.
If you need something to be able to added dynamically, c# attributes aren't the way. Look into storing the data in xml. I recently did a project that i started w/ attributes, but eventually moved to serialization w/ xml.
Why do you need to? Attributes give extra information for reflection, but if you externally know which properties you want you don't need them.
You could store meta data externally relatively easily in a database or resource file.
Like mentionned in a comment below by Deczaloth, I think that metadata is fixed at compile time. I achieve it by creating a dynamic object where I override GetType() or use GetCustomType() and writing my own type. Using this then you could...
I tried very hard with System.ComponentModel.TypeDescriptor without success. That does not means it can't work but I would like to see code for that.
In counter part, I wanted to change some Attribute values.
I did 2 functions which work fine for that purpose.
// ************************************************************************
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);
}
}
}
When faced with this situation, yet another solution might be questioning you code design and search for a more object-oriented way. For me, struggling with unpleasant reflection work arounds is the last resort. And my first reaction to this situation would be re-designing the code. Think of the following code, which tries to solve the problem that you have to add an attribute to a third-party class you are using.
class Employee {} // This one is third-party.
And you have code like
var specialEmployee = new Employee();
// Here you need an employee with a special behaviour and want to add an attribute to the employee but you cannot.
The solution might be extracting a class inheriting from the Employee class and decorating it with your attribute:
[SpecialAttribute]
class SpecialEmployee : Employee
{
}
When you create an instance of this new class
var specialEmployee = new SpecialEmployee();
you can distinguish this specialEmployee object from other employee objects. If appropriate, you may want to make this SpecialEmployee a private nested class.

Create property at runtime

is it possible to create a property on a type at runtime? My type "Account" has a predefined bunch of properties such has "ID" and "Account Name" and it implements INotifyPropertyChanged, I wanted to add properties to this type at runtime, so a getter and a setter and the setter would call a method Notify passing in it's property name i.e
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChanged("Name");
}
}
Yes, but not with "normal" CLR types. You can achieve that, actually that type was created especially for functionalities like that: DynamicObject
Look on example code provided of the class that implements DynamicObject, like
public class DynamicDictionary : DynamicObject
{
...
}
and after you are able to use it like:
dynamic person = new DynamicDictionary();
// Adding new dynamic properties.
person.FirstName = "Ellen";
person.LastName = "Adams";
You can use Reflection.Emit to dynamically create new classes that inherit from your class, and then add the properties to that new type.
As it inherits your own type, it can be considered as being an "extension" for that type.
I must warn you that this path is a complicated one, and you will probably produce code that you will never understand again after finishing the job!
Also you will have understand how MSIL code works. It is a bit odd, and inverted thing. You have to do things quite the oposite way you would expect in a language such as C#. You must push and pop values from stacks to pass as argument to a function, and you must activelly discard unused return values from functions... and so on.
And YES, I am trying to make you afraid of this... it is such a painful way ;)
Consider other alternatives before falling to this one.
There is a lot of material in SO already on this matter: https://stackoverflow.com/questions/tagged/reflection.emit
CodeProject article explaining Reflection.Emit:
Dynamic Type Using Reflection.Emit
Either you use a Dynamic Object or extend behavior via Extension Methods. I don't know of other options.
no, that is not possible with c# objects
you can make dictionary like classes, which can store different properties like in the question with the DynamicObject
what you can do is is creating new class types by reflection, and they can contain new properties. but there is no easy way to access these

Attributes creating fields in C#

Alright, so after a few hours of me playing around to no avail, I built a model:
[AttributeUsage(AttributeTargets.All)]
public class PublicAttribute : System.Attribute
{
public enum Access { Public, Private }
public PublicAttribute(string Name, Access acs)
{
}
public PublicAttribute(string Name, Access acs, Action get, Action set)
{
}
}
So that if somebody were to do something like this:
[Public("PublicProperty", PublicAttribute.Access.Public)]
private string PrivateProperty = "hello";
or
[Public("PublicProperty", PublicAttribute.Access.Public, ()=>{return PrivateProperty;}, ()=>{PrivateProperty = value})]
private string PrivateProperty = "hello";
and then if somebody was trying to access PrivateProperty, they could just go:
ContainingClass.PublicProperty = //ect
"PublicProperty". and that is because of the attribute, and it would use those get/set accessors.
What I'd like to know:
Is this even possible?
Is there something that already does this?
If its possible, (even if there is something else) How do i do this?
Basically no to all 3, as C# is a strongly typed language. Even with duck typing what you're trying to achieve doesn't fit the language.
The attributes you've written allow you to interrogate the properties that have those attributes in the class, but you still need to use Reflection to discover which properties of the attribute class are set. The syntax you want to use is checked at compile-time.
No, this is not possible using attributes. Properties are part of the class metadata emitted by the C# compiler, and the C# compiler does not consider custom attributes.
You may be able to do this by using a post-processor such as PostSharp, which can rewrite your assembly after the fact, and can be instructed to consider custom attributes. However, you still wouldn't be able to include a delegate in the attribute: the set of types that can be stored in attribute state is extremely limited.
Microsoft made the WebMethodAttribute in a way reminiscent of what you're trying to describe making it represent more permission than C# public, effectively making a method available outside the application domain to the entire Internet (a very global scope). You might read it to get real implementation insight and ideas.
But you're hitting it very simply. You'll have to program some infrastructure to make it work. It's not automatic and you don't have access to Microsoft's source code for all the details.

What are attributes in .NET?

What are attributes in .NET, what are they good for, and how do I create my own attributes?
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.
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
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!
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
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
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.
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.
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.
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
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.
Attributes are also commonly used for Aspect Oriented Programming. For an example of this check out the PostSharp project.

Categories

Resources