Browse DevX
Sign up for e-mail newsletters from DevX


Defining and Using Custom Attribute Classes in C#

.NET has made flexible, loosely-coupled "declarative" programming available through Attributes. .NET also allows you to create your own custom Attribute classes.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

he complex, component-style development that businesses expect out of modern software developers requires greater design flexibility than the design methodologies of the past. Microsoft's .NET Framework makes extensive use of attributes to provide added functionality through what is known as "declarative" programming. Attributes enhance flexibility in software systems because they promote loose coupling of functionality. Because you can create your own custom attribute classes and then act upon them, you can leverage the loose coupling power of attributes for your own purposes.

The .NET Framework makes many aspects of Windows programming much simpler. In many cases, the Framework's use of metadata that .NET compilers bind to assemblies at compile time makes tricky programming easier. Indeed, the use of intrinsic metadata makes it possible for .NET to relieve us from "DLL Hell."

Lucky for us, the designers of the .NET framework did not choose to keep these metadata "goodies" hidden away under the covers. The designers gave us the Reflection API through which a .NET application can programmatically investigate this metadata. An application can "reflect" upon any imaginable aspect of a given assembly or on its contained types and their members.

Binding the metadata to the executable provides many advantages. It makes the assemblies in .NET fully self-describing. This allows developers to share components across languages and eliminates the need for header files. (They can become out-of-date relative to the implementation code.)

With all this positive news about .NET metadata it seems hard to believe there could be anything more to the story—but there is. You can create your own application-specific metadata in .NET and then use that metadata for any purpose you can imagine.

Developers define their own application-specific metadata through the use of Custom Attributes. Because these attribute values become just another part of the metadata bound into an assembly, the custom attribute values are available for examination by the Reflection API.

We commonly refer to properties of a class and their values as "attributes." So what really is the difference between properties and custom attributes?
In this article, you'll learn how to define custom attribute classes, how to apply attributes to classes and methods in your source code, and you'll learn how to use the Reflection API to retrieve and act upon these values.

How Does .NET Use Attributes in the Common Language Runtime?
Before you start to consider what you can accomplish with your own custom attribute classes, let's examine some of the standard attributes that the Common Language Runtime already makes available.

The [WebService] attribute provides a simple example—it lets you turn any public method of a WebService subclass into a method that you can expose as part of the Web service merely by attaching the [WebMethod] attribute to the method definition.

public class SomeWebService : System.Web.Services.WebService { [WebMethod] public DataSet GetDailySales( ) { // code to process the request... } }

You simply attach the [WebMethod] attribute to the method and .NET handles everything else for you behind the scenes.

Using the [Conditional] attribute allows you to make a given method conditional based on the presence or absence of the specified preprocessing symbol. For example, the following code:

public class SomeClass { [Conditional( "DEBUG" )] public void UnitTest( ) { // code to do unit testing... } }

indicates that the UnitTest( ) method of this class is "conditional" based on the presence of the preprocessing symbol "DEBUG". The really interesting part is what actually happens. The compiler stubs out all calls to the method when the condition fails rather than attempt to nullify the behavior of the method the way an #if...#endif pre-processing directive does. This is a much cleaner approach, and again we didn't have to do much of anything to utilize this functionality.

Attributes utilize positional and/or named parameters. In the example using the [Conditional] attribute, the symbol specification is a positional parameter. You must always supply positional parameters.

To look at named parameters, let's return to the [WebMethod] attribute example. This attribute has a named parameter called Description. To use it you would change the line to read:

[WebMethod( Description = "Sales volume" )]

Named parameters are optional and you write them using the name of the parameter followed by the assignment of a value. Named parameters follow after you've specified all positional parameters.

I will talk more about named and positional parameters later in this article when I show you how to create and apply your own Attribute class.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date