Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

msdnmagazine.com February 2014 63


You simply create the new class, passing an instance of the old


class as a parameter for its constructor. When you execute the


program, you can see it has the logging, as shown in Figure 6.


You might be thinking: “OK, the idea is good, but it’s a lot of work: I


have to implement all the classes and add the aspect to all the methods.


Th at will be diffi cult to maintain. Is there another way to do it?” With


the .NET Framework, you can use refl ection to get all methods and


execute them. Th e base class library (BCL) even has the RealProxy


class (bit.ly/18MfxWo) that does the implementation for you.


Creating a Dynamic Proxy with RealProxy


Th e RealProxy class gives you basic functionality for proxies. It’s


an abstract class that must be inherited by overriding its Invoke


method and adding new functionality. Th is class is in the name-


space System.Runtime.Remoting.Proxies. To create a dynamic


proxy, you use code similar to Figure 7.


In the constructor of the class, you must call the constructor of


the base class, passing the type of the class to be decorated. Th en


you must override the Invoke method that receives an IMessage


parameter. It contains a dictionary with all the parameters passed for


the method. Th e IMessage parameter is typecast to an IMethod-


CallMessage, so you can extract the parameter MethodBase (which


has the MethodInfo type).


Th e next steps are to add the aspect you want before calling the


method, call the original method with methodInfo.Invoke and


then add the aspect aft er the call.


You can’t call your proxy directly, because DynamicProxy isn’t


an IRepository. Th at means you can’t call it like this:


IRepository<Customer> customerRepository =
new DynamicProxy<IRepository<Customer>>(
new Repository<Customer>());

To use the decorated repository, you must use the GetTrans-


parentProxy method, which will return an instance of


IRepository. Every method of this instance that’s called


will go through the proxy’s Invoke method. To ease this process,


you can create a Factory class to create the proxy and return the


instance for the repository:


pu blic class RepositoryFactory
{
public static IRepository<T> Create<T>()
{
var repository = new Repository<T>();
var dynamicProxy = new DynamicProxy<IRepository<T>>(repository);
return dynamicProxy.GetTransparentProxy() as IRepository<T>;
}
}

Th at way, the main program will be similar to Figure 8.


When you execute this program, you get a similar result as


before, as shown in Figure 9.


As you can see, you’ve created a dynamic proxy that allows add-


ing aspects to the code, with no need to repeat it. If you wanted to


static void Main(string[] args)
{
Console.WriteLine("***\r\n Begin program - logging with dynamic proxy\r\n");
// IRepository<Customer> customerRepository =
// new Repository<Customer>();
// IRepository<Customer> customerRepository =
// new LoggerRepository<Customer>(new Repository<Customer>());
IRepository<Customer> customerRepository =
RepositoryFactory.Create<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 - logging with dynamic proxy\r\n***");
Console.ReadLine();
}

Figure 8 The Main Program with a Dynamic Proxy


Figure 9 Program Execution with Dynamic Proxy


class AuthenticationProxy<T> : RealProxy
{
private readonly T _decorated;

public AuthenticationProxy(T decorated)
: base(typeof(T))
{
_decorated = decorated;
}

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

public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;

if (Thread.CurrentPrincipal.IsInRole("ADMIN"))
{
try
{
Log("User authenticated - You can execute '{0}' ",
methodCall.MethodName);
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);

return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
catch (Exception e)
{
Log(string.Format(
"User authenticated - Exception {0} executing '{1}'", e),
methodCall.MethodName);
return new ReturnMessage(e, methodCall);
}
}
Log("User not authenticated - You can't execute '{0}' ",
methodCall.MethodName);
return new ReturnMessage(null, null, 0,
methodCall.LogicalCallContext, methodCall);
}
}

Figure 1 0 An Authentication Proxy

Free download pdf