Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

66 msdn magazine Aspect-Oriented Programming


ever, note that RealProxy isn’t a replacement for other AOP tools,


such as PostSharp. PostSharp uses a completely diff erent method.


It will add intermediate language (IL) code in a post-compilation


step and won’t use refl ection, so it should have better performance


than RealProxy. You’ll also have to do more work to implement an


aspect with RealProxy than with PostSharp. With PostSharp, you


need only create the aspect class and add an attribute to the class


(or the method) where you want the aspect added, and that’s all.


On the other hand, with RealProxy, you’ll have full control of


your source code, with no external dependencies, and you can


extend and customize it as much as you want. For example, if


you want to apply an aspect only on methods that have the Log


attribute, you could do something like this:


public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;
if (!methodInfo.CustomAttributes
.Any(a => a.AttributeType == typeof (LogAttribute)))
{
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
...

Besides that, the technique used by RealProxy (intercept code


and allow the program to replace it) is powerful. For example, if you


want to create a mocking framework, for creating generic mocks


and stubs for testing, you can use the RealProxy class to intercept


all calls and replace them with your own behavior, but that’s a sub-


ject for another article! Q


BRUNO SONNINO is a Microsoft Most Valuable Professional (MVP) located in Brazil.


He’s a developer, consultant, and author, having written fi ve Delphi books, pub-


lished in Portuguese by Pearson Education Brazil, and many articles for Brazilian


and U.S. magazines and Web sites.


THANKS to the following Microsoft Research technical experts for reviewing


this article: James McCaff rey, Carlos Suarez and Johan Verwey


Figure 17 A Flexible Proxy


class DynamicProxy<T> : RealProxy
{
private readonly T _decorated;
private Predicate<MethodInfo> _filter;

public event EventHandler<IMethodCallMessage> BeforeExecute;
public event EventHandler<IMethodCallMessage> AfterExecute;
public event EventHandler<IMethodCallMessage> ErrorExecuting;
public DynamicProxy(T decorated)
: base(typeof(T))
{
_decorated = decorated;
Filter = m => true;
}

public Predicate<MethodInfo> Filter
{
get { return _filter; }
set
{
if (value == null)
_filter = m => true;
else
_filter = value;
}
}

private void OnBeforeExecute(IMethodCallMessage methodCall)
{
if (BeforeExecute != null)
{
var methodInfo = methodCall.MethodBase as MethodInfo;
if (_filter(methodInfo))
BeforeExecute(this, methodCall);
}
}

private void OnAfterExecute(IMethodCallMessage methodCall)
{

if (AfterExecute != null)
{
var methodInfo = methodCall.MethodBase as MethodInfo;
if (_filter(methodInfo))
AfterExecute(this, methodCall);
}
}

private void OnErrorExecuting(IMethodCallMessage methodCall)
{
if (ErrorExecuting != null)
{
var methodInfo = methodCall.MethodBase as MethodInfo;
if (_filter(methodInfo))
ErrorExecuting(this, methodCall);
}
}

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

OnBeforeExecute(methodCall);
try
{
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
OnAfterExecute(methodCall);

return new ReturnMessage(
result, null, 0, methodCall.LogicalCallContext, methodCall);
}
catch (Exception e)
{
OnErrorExecuting(methodCall);
return new ReturnMessage(e, methodCall);
}
}
}

public class RepositoryFactory
{
private static void Log(string msg, object arg = null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg, arg);
Console.ResetColor();
}
public static IRepository<T> Create<T>()
{
var repository = new Repository<T>();
var dynamicProxy = new DynamicProxy<IRepository<T>>(repository);
dynamicProxy.BeforeExecute += (s, e) => Log(
"Before executing '{0}'", e.MethodName);
dynamicProxy.AfterExecute += (s, e) => Log(
"After executing '{0}'", e.MethodName);
dynamicProxy.ErrorExecuting += (s, e) => Log(
"Error executing '{0}'", e.MethodName);
dynamicProxy.Filter = m => !m.Name.StartsWith("Get");
return dynamicProxy.GetTransparentProxy() as IRepository<T>;
}
}

Figure 18 A Repository Factory


that Sets the Aspect Events and Filter

Free download pdf