Académique Documents
Professionnel Documents
Culture Documents
NET Framework, attributes are used for many reasons - from defining which classes are
serializable to choosing which methods are exposed in a Web service. Attributes allow you to add
descriptions to classes, properties, and methods at design time that can then be examined at runtime
via reflection.
n .NET Framework, atributele sunt folosite pentru multe motive - de la definirea claselor care sunt serializable la
alegerea metodelor care sunt expuse de la un serviciu web. Atributele v permit s adugai descrieri pentru clase,
proprieti i metode de la timpul de proiectare care pot fi examinate la execuie prin reflexie.
Attributes are special classes that can be applied to classes, properties, and methods at design time.
Attributes provide a way to describe certain aspects of an element or determine the behavior of other
classes acting upon the element. Those descriptions and behaviors can then be accessed and
examined at runtime. You can think of attributes as a way of adding special modifiers to your class
members.
Atributele sunt clasele speciale care pot fi aplicate la clase, proprieti i metode de la timpul de proiectare. Atributele
ofer un mod de a descrie anumite aspecte ale unui element sau determina comportamentul de alte clase care
acioneaz asupra elementului. Aceste descrieri i comportamente pot fi accesate i examinate la runtime. V putei gndi
de atribute ca un mod de a aduga modificatori speciale pentru clasa dumneavoastra de membri.
For example, if you have written Web services, you are no doubt aware that the WebMethod attribute
must be applied to methods for them to be exposed through the service. This is a perfect example to
show the usage of attributes because the WebMethod attribute is used to extend the programming
model. There is no built-in way in C# of signifying that a method should be exposed through the Web
service (as there is, for example, of signifying that a method should be private), so the WebMethod
attribute was written to satisfy this need.
using them. However, there are instances when it is better to place the attributes inside
of a common, lightweight, shared assembly. This type of configuration allows clients to
use the attributes without referencing unneeded assemblies.
Using attributes
Before we get into the details of how to create custom attributes, we need to look at how
they are used. For example, assume we have an attribute called "Hide" which effectively
hides properties so that they don't print to the screen. If we were to apply this attribute to
the "SSN" property, our code would look like Listing A.
Listing A
[Hide()]
publicstring SSN
{
get { return _ssn; }
set { _ssn = value; }
}
As a more complicated example, assume we have an attribute called "Alias". This
attribute's job is to determine the aliases a property may have. This allows the property's
value to be mapped into another property even if the property names don't match. This
attribute accepts a series of string values to hold as the mapping names (Listing B).
Listing B
[Alias("FirstName", "First")]
publicstring FName
{
get { return _fName; }
set { _fName = value; }
}
In this case, the property "FName" is mapped to both "FirstName" and "First." See the
example application for more detail on this type of usage.
Creating attributes
Creating attributes is a simple process. You define a class with the data you want to store,
and inherit from the System.Attribute class. Listing C is an example of how to create the
"Alias" attribute shown in the previous section.
Listing C
classAlias : System.Attribute
{
string[] _names;
public Alias(paramsstring[] names)
{
this.Names = names;
}
publicstring[] Names
{
get { return _names; }
set { _names = value; }
}
}
As you can see, this is just a normal class and, with the exception of inheriting from
System.Attribute, we didn't have to do anything special to enable it to be an attribute. We
simply defined the constructor that needed to be used and created a property and private
member to store the data.
Listing D is a much simpler attribute the "Hide" attribute. This attribute requires no
constructor (it uses the default) and doesn't store any data. This is because this attribute is
simply a "flag" type attribute:
Listing D
classHide : System.Attribute
{
//This is a simple attribute, that only requires
// the default constructor.
}
Let's assume that we are examining a class and we want to determine which properties
have the Alias attribute applied and which aliases are listed. Listing E implements this
logic:
Listing E
privateDictionary<string, string> GetAliasListing(Type destinationType)
{
//Get all the properties that are in the
// destination type.
PropertyInfo[] destinationProperties = destinationType.GetProperties();
Dictionary<string, string> aliases = newDictionary<string, string>();
foreach (PropertyInfo property in destinationProperties)
{
//Get the alias attributes.
object[] aliasAttributes =
property.GetCustomAttributes(typeof(Alias), true);
//Loop through the alias attributes and
// add them to the dictionary.
foreach (object attribute in aliasAttributes)
foreach (string name in ((Alias)attribute).Names)
aliases.Add(name, property.Name);
//We also need to add the property name
// as an alias.
aliases.Add(property.Name, property.Name);
}
return aliases;
}
The most important lines of this section of code are where we call GetCustomAttributes
and the section where we loop through the attributes and extract the aliases.
The GetCustomAttributes method is available from the PropertyInfo class that we
extracted from the object's Type. In the usage shown above, we tell the
GetCustomAttributes method what type of attribute we're looking for and also pass "true"
to enable it to pull inherited attributes. The GetCustomAttributes method returns an object
array if any matching attributes are found. There is also another overload of the method
that allows you to pull all attributes on the property, regardless of the attribute's type.
Once we have the attributes, we need to examine them and extract the information we're
looking for. This is done by looping through the objects in the array given to us from
GetCustomAttributes and casting each object into the type of attribute we're looking for.
After the object has been cast, we can access properties of the attribute the same way we
would access properties of any other class.
As I previously mentioned, reading the attribute is the hardest part. However, once you've
written the code to read an attribute, it is fairly easy to remember and implement in the
future.
Alias This is the same Alias attribute mentioned above. This attribute is used
when you want to translate one type of object into another type of object. For example,
if you have a Customer object and an Address object, you could translate both of those
into a combined Person object, which contains the person's name and address. This
would be used when a direct cast can't be made.
Hide This simply instructs the PrintObject() method to not print the current
property out to the screen. This is used on the SSN property of the Customer object.
The sample application includes comments for every step it takes in implementing and
reading the attributes. Take a look and I'm sure you'll see some functionality you can take
advantage of in your own applications.
Attributes are a powerful feature in the C# programming language that can add metadata information
to your assemblies.
An attribute is actually an object that is associated with any of these elements: Assembly, Class,
Method, Delegate, Enum, Event, Field, Interface, Property and Struct. They can be used to associate
declarative information -- you can retrieve such information at runtime at a later point of time if need
be using reflection. In other words, you can use attributes to inject additional information to the
assemblies that can be queried at runtime if needed using reflection. An attribute comprises of its
name and optionally, a list of parameters. The attribute name corresponds to the attribute class.
You can take advantage of attributes to validate the business objects in your application. There are
two types of attributes -- intrinsic attributes and custom attributes. While the former is available as part
of the .Net framework, the latter can be implemented by deriving a class from the System.Attribute
class. The MSDN states: "An attribute is a piece of additional declarative information that is specified
for a declaration."
Let's now get into some code. The Obsolete attribute can be used to denote a method as obsolete -one that shouldn't be used anymore as it is no longer needed or may have some other alternative.
The following code snippet illustrates how you can use the Obsolete attribute on top of a method
declaration.
[Obsolete("This method is obsolete...")]
public static void DoSomeWork()
{
//Some code
}
If you use this method in your code and compile your program, you would see a warning displayed in
the output window of the Visual Studio IDE. So, you can ignore this warning if you want to. Now, what
if you want your developers no to use this method at all? Well, you can then use the second
parameter (it's optional though) while declaring the Obsolete attribute. Here's the modified version of
the DoSomeWork() method. Notice the usage of the Boolean parameter this time.
[Obsolete("This method is obsolete...", true)]
public static void DoSomeWork()
{
//Some code
When you pass "true" as the second optional parameter this time and compile your program, the code
wouldn't compile at all. That's what you wanted to do, isn't it?
Custom attributes
In this section we will explore how we can implement custom attributes. Custom attributes are classes
that inherit the System.Attribute class. So, to implement a custom attribute class, create a new class
and derive it from System.Attribute class as shown below.
using System;
public class CustomAttribute : Attribute
{
}
To control the usage of custom attributes, you can take advantage of the AttributeUsage class. This
class contains properties like, ValidOn, AllowMultiple and Inherited which can be used to control the
usage of your custom attribute.
The following snippet of code illustrates a modified version of our custom attribute class. Note the
usage of a constructor that accepts a string as an argument and assigns it to the private string
member of the class. This is just for illustration purposes only.
[AttributeUsage(AttributeTargets.All)]
public class CustomAttribute : Attribute
{
private string text;
public CustomAttribute(string text)
{
this.Text = text;
}
public string Text
{
get
{
return this.text;
}
set
{
this.text = value;
}
}
}
You can also specify the attribute targets that your custom attribute should be applied to. Here's how
you can do it.
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class CustomAttribute : Attribute
{
You can now use reflection to display all the attributes that are applied to a particular object using the
following code snippet.
MemberInfo memberInfo = typeof(CustomAttribute);
object[] attributes = memberInfo.GetCustomAttributes(true);
for (int i = 0, j = attributes.Length; i < j; i++)
{
Console.WriteLine(attributes[i]);
}
Now consider the following class on which we would apply our custom attribute.
[CustomAttribute("Hello World...")]
public class SomeClass
{
}
Note how the custom attribute has been used and a text passed as argument to it. The following code
snippet illustrates how you can print the content of the Text property.
MemberInfo memberInfo = typeof(SomeClass);
object[] attributes = memberInfo.GetCustomAttributes(true);
foreach (object attribute in attributes)
{
CustomAttribute customAttribute = attribute as CustomAttribute;
if (customAttribute != null)
Console.WriteLine("Text = {0}", customAttribute.Text);
else
Console.WriteLine();
}