In this article, I drive into aspect oriented programming and discuss it in enough detail that is relevant to goals of this project.

Aspect Oriented Programming, or simply by acronym, AOP, is a style of programming that, certain run-time descriptions and tasks which are re-usable and common in many contexts, are applied using declarative manner instead of imperative style. What does that supposed to mean ? It simply means you don’t have to call some functions or make some assignments, yes, no function call, and that, only a description is enough to state what is supposed to happen.

The declarative way to programming, is very powerful. Because by simply looking at the description, you know what is supposed to happen. It not only saves your time, but also your code will be much more maintainable, and readable. And, adding some functionalities become easier by just stating more descriptions. This has been much adapted by many, including LINQ, Attributes in .NET, and Inversion of Control/Dependency Injection patterns.

Some of the examples of AOP include:

  • Serialization of methods using monitors
  • Asynchronous method invocation
  • Tracing and Logging
  • Security Checks
  • Business and Operational contracts, or more generally Design-By-Contract

We start, by looking at .NET Attributes. Attributes in .NET, which Microsoft calls, Attribute-Based Programming, are pieces of meta-data that, emit to the resulting assembly when compiled. They provide hints to compiler and execution. They can be applied to assemblies, classes, interfaces, structs, methods, properties, fields and parameters. Here is an example of when, an attribute becomes a hint to the compiler:

  1: [Obsolete] 
  2: public void MyMethod() 
  3: { 
  4: }

The System.ObsoleteAttribute provides a hint to the compiler, that, this method is obsolete and should not be used. So that the compiler will generate a warning if this method was used. Note that, I have ommited Attribute when I used System.ObsoleteAttribute. This is natural in C#, since compiler will itself attach an Attribute to the type specified by you.

So how it happens ? attributes are processed before the assembly is generated. The compiler will itself initialize a new instance from them, serialize them, and put them in metadata of the generated assembly. So, attributes must be serializable and only the data that can be serialized can be kept in metadata of the resulting assembly.

Attributes can also contain information about execution. They can not execute anything themselves in run-time though. see the following example from ASP.NET MVC 2.0 framework:

 
  1: [Authorized(Roles = "Administrator")] 
  2: public ActionResult ManageAccounts() 
  3: {
  4:      return View();
  5: }

The above controller action, states that a typical url like http://mydomain.com/Account/ManageAccounts can only be viewed by members of Administrator. If any other user tries to view manage account section of the site, they are given an error and probably redirected to some informative page.

Well, You probably ask, attributes weren’t supposed to execute anything themselves, If so, How does this happen ? Well, It is natural. A router mechanism that calls ManageAccounts method, checks for attributes that are applied to this method, in run-time, and takes appropriate actions. Take this as an example, which has been copied from MSDN, http://msdn.microsoft.com/en-us/library/system.reflection.methodattributes.aspx

  1: using System;
  2: using System.Reflection;
  3: 
  4: class AttributesSample
  5: {
  6:     public void Mymethod (int int1m, out string str2m, ref string str3m)
  7:     {
  8:         str2m = "in Mymethod";
  9:     }
 10: 
 11:     public static int Main(string[] args)
 12:     {      
 13:         Console.WriteLine ("Reflection.MethodBase.Attributes Sample");
 14: 
 15:         // Get the type of the chosen class.
 16:         Type MyType = Type.GetType("AttributesSample");
 17: 
 18:         // Get the method Mymethod on the type.
 19:         MethodBase Mymethodbase = MyType.GetMethod("Mymethod");
 20: 
 21:         // Display the method name and signature.
 22:         Console.WriteLine("Mymethodbase = " + Mymethodbase);
 23: 
 24:         // Get the MethodAttribute enumerated value.
 25:         MethodAttributes Myattributes = Mymethodbase.Attributes;
 26: 
 27:         // Display the flags that are set.
 28:         PrintAttributes(typeof(System.Reflection.MethodAttributes), (int) Myattributes);
 29:         return 0;
 30:     }
 31: 
 32: 
 33:     public static void PrintAttributes(Type attribType, int iAttribValue)
 34:     {
 35:         if (!attribType.IsEnum) {Console.WriteLine("This type is not an enum."); return;}
 36: 
 37:         FieldInfo[] fields = attribType.GetFields(BindingFlags.Public | BindingFlags.Static);
 38:         for (int i = 0; i < fields.Length; i++)
 39:         {
 40:             int fieldvalue = (Int32)fields[i].GetValue(null);
 41:             if ((fieldvalue & iAttribValue) == fieldvalue)
 42:             {
 43:                 Console.WriteLine(fields[i].Name);
 44:             }
 45:         }
 46:     }
 47: }
 48: 

So, It is possible to query attributes, simply meta-data in an assembly, in run-time and take action upon it. It is also possible to write custom attributes, which the following example points out, where the custom attribute is generated easily by attribute code-snippet shipped with Microsoft Visual Studio. I will not dive deeper in creating custom attributes. More information can be found in MSDN about this topic. Microsoft has also explained this topic in depth with lots of exotic samples.

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: using System.Reflection;
  6: 
  7: namespace ConsoleApplication5
  8: {
  9:     class Program
 10:     {
 11:         [AttributeUsage(AttributeTargets.Method, 
 12:                             Inherited = false, 
 13:             AllowMultiple = true)]
 14:         sealed class HelloAttribute : Attribute
 15:         {
 16:             // See the attribute guidelines at 
 17:             //  http://go.microsoft.com/fwlink/?LinkId=85236
 18:             readonly string positionalString;
 19: 
 20:             // This is a positional argument
 21:             public HelloAttribute(string positionalString)
 22:             {
 23:                 this.positionalString = positionalString;
 24: 
 25:                 // TODO: Implement code here
 26:                 while (true) { }
 27:             }
 28: 
 29:             public string PositionalString
 30:             {
 31:                 get { return positionalString; }
 32:             }
 33: 
 34:             // This is a named argument
 35:             public int NamedInt { get; set; }
 36:         }
 37: 
 38:         [Hello("Arcane_Master")]
 39:         [Hello("CodePlex")]
 40:         public void MyMethod()
 41:         {
 42:             Type type = this.GetType();
 43:             MethodInfo methodInfo = type.GetMethod("MyMethod");
 44:             foreach (string attribute in methodInfo.GetCustomAttributes(false)
 45:                 .OfType<HelloAttribute>()
 46:                 .Select(x => x.PositionalString))
 47:             {
 48:                 Console.WriteLine("Hello, " + attribute);
 49:             }
 50:         }
 51: 
 52:         static void Main(string[] args)
 53:         {
 54:             Program target = new Program();
 55:             target.MyMethod();
 56:         }
 57:     }
 58: }
 59: 

Remember that, As I’ve said, AOP is about declarative manner of doing repeated things which needed hard-coded logic of the programmer. What attributes lack, is that fetching them must be done manually by the programmer. If an attribute is applied, It can not execute by itself. Something that one expects from the following code, Is not done by means of an attribute:

  1: [Trace] 
  2: public void MyMethod() 
  3: {
  4: }

There has been, many workarounds about this lack of functionality. To be more specific, There is a workaround that does not use any 3rd party library, but the .NET Framework itself, using object contexts. I will not drive deep into this topic, but this workaround is costly, both in execution time, and programmer’s effort. One of the most beautiful solutions around this, is PostSharp. Well, I will give a good introduction about PostSharp in a dedicated article.

But this is not the only functionality that lacks. When we initialize an attribute, we can only give an expression of the following:

  • A constant expression
  • An array creation of a parameter type

And, This means that the following are not possible:

  • An object creation and invocation
  • Calling static method and using static properties
  • Usage of generic types
  • Using lambda expressions

This restriction, is a huge restriction. We are abided of many flexibilities while using attributes. But still, attributes are, nevertheless, important declarative aspect of .NET languages.

Last edited Sep 14, 2010 at 9:54 AM by arcane_master, version 8

Comments

No comments yet.