Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

msdnmagazine.com February 2014 61


In this article, I’ll explain the basics of AOP and then detail how


to make it easier by using a dynamic proxy via the Microsoft .NET


Framework class RealProxy.


Implementing AOP


Th e biggest advantage of AOP is that you only have to worry about


the aspect in one place, programming it once and applying it in all


the places where needed. Th ere are many uses for AOP, such as:



  • Implementing logging in your application.

  • Using authentication before an operation (such as allowing


some operations only for authenticated users).



  • Implementing validation or notifi cation for property


setters (calling the PropertyChanged event when a


property has been changed for classes that implement


the INotifyPropertyChanged interface).



  • Changing the behavior of some methods.


As you can see, AOP has many uses, but you must wield it with


care. It will keep some code out of your sight, but it’s still there, run-


ning in every call where the aspect is present. It can have bugs and


severely impact the performance of the application. A subtle bug in


the aspect might cost you many debugging hours. If your aspect isn’t


used in many places, sometimes it’s better to add it directly to the code.


AOP implementations use some common techniques:



  • Adding source code using a pre-processor, such as the


one in C++.



  • Using a post-processor to add instructions on the


compiled binary code.



  • Using a special compiler that adds the code while compiling.

  • Using a code interceptor at run time that intercepts


execution and adds the desired code.


In the .NET Framework, the most commonly used of these tech-


niques are post-processing and code interception. Th e former is the


technique used by PostSharp (postsharp.net) and the latter is used by


dependency injection (DI) containers such as Castle DynamicProxy


(bit.ly/ JzE631) and Unity (unity.codeplex.com). Th ese tools usually use a design


pattern named Decorator or Proxy to perform the code interception.


The Decorator Design Pattern


Th e Decorator design pattern solves a common problem: You have


a class and want to add some functionality to it. You have several


options for that:



  • You could add the new functionality to the class directly.


However, that gives the class another responsibility and


hurts the “single responsibility” principle.



  • You could create a new class that executes this functionality


and call it from the old class. Th is brings a new problem: What


if you also want to use the class without the new functionality?


static void Main(string[] args)
{
Console.WriteLine("***\r\n Begin program - no logging\r\n");
IRepository<Customer> customerRepository =
new Repository<Customer>();
var customer = new Customer
{
Id = 1,
Name = "Customer 1",
Address = "Address 1"
};
customerRepository.Add(customer);
customerRepository.Update(customer);
customerRepository.Delete(customer);
Console.WriteLine("\r\nEnd program - no logging\r\n***");
Console.ReadLine();
}

Figure 2 The Main Program, with No Logging


Figure 3 Output of the Program with No Logging


p ublic class LoggerRepository<T> : IRepository<T>
{
private readonly IRepository<T> _decorated;

public LoggerRepository(IRepository<T> decorated)
{
_decorated = decorated;
}

private void Log(string msg, object arg = null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg, arg);
Console.ResetColor();
}

public void Add(T entity)
{
Log("In decorator - Before Adding {0}", entity);
_decorated.Add(entity);
Log("In decorator - After Adding {0}", entity);
}

public void Delete(T entity)
{
Log("In decorator - Before Deleting {0}", entity);
_decorated.Delete(entity);
Log("In decorator - After Deleting {0}", entity);
}

public void Update(T entity)
{
Log("In decorator - Before Updating {0}", entity);
_decorated.Update(entity);
Log("In decorator - After Updating {0}", entity);
}

public IEnumerable<T> GetAll()
{
Log("In decorator - Before Getting Entities");
var result = _decorated.GetAll();
Log("In decorator - After Getting Entities");
return result;
}

public T GetById(int id)
{
Log("In decorator - Before Getting Entity {0}", id);
var result = _decorated.GetById(id);
Log("In decorator - After Getting Entity {0}", id);
return result;
}
}

Figure 4 The Logger Repository

Free download pdf