Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

64 msdn magazine Aspect-Oriented Programming


add a new aspect, you’d only need to create a new class, inherit from


RealProxy and use it to decorate the fi rst proxy.


If your boss comes back to you and asks you to add authoriza-


tion to the code, so only administrators can access the repository,


you could create a new proxy as shown in Figure 10.


Th e repository factory must be changed to call both proxies, as


shown in Figure 11.


When you change the main program to Figure 12 and run it,


you’ll get the output shown in Figure 13.


Th e program executes the repository methods twice. Th e fi rst


time, it runs as an admin user and the methods are called. Th e sec-


ond time, it runs as a normal user and the methods are skipped.


That’s much easier, isn’t it? Note that the factory returns an


instance of IRepository, so the program doesn’t know if it’s


using the decorated version. Th is respects the Liskov Substitution


Principle, which says that if S is a subtype of T, then objects of type


T may be replaced with objects of type S. In this case, by using an


IRepository interface, you could use any class that


implements this interface with no change in the program.


Filtering Functions


Until now, there was no filtering in the functions; the aspect is


applied to every class method that’s called. Often this isn’t the


desired behavior. For example, you might not want to log the


retrieval methods (GetAll and GetById). One way to accomplish


this is to fi lter the aspect by name, as in Figure 14.


Th e program checks if the method starts with “Get.” If it does, the


program doesn’t apply the aspect. Th is works, but the fi ltering code is


repeated three times. Besides that, the fi lter is inside the proxy, which


will make you change the class every time you want to change the


proxy. You can improve this by creating an IsValidMethod predicate:


private static bool IsValidMethod(MethodInfo methodInfo)
{
return !methodInfo.Name.StartsWith("Get");
}

static void Main(string[] args)
{
Console.WriteLine(
"***\r\n Begin program - logging and authentication\r\n");
Console.WriteLine("\r\nRunning as admin");
Thread.CurrentPrincipal =
new GenericPrincipal(new GenericIdentity("Administrator"),
new[] { "ADMIN" });
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\nRunning as user");
Thread.CurrentPrincipal =
new GenericPrincipal(new GenericIdentity("NormalUser"),
new string[] { });
customerRepository.Add(customer);
customerRepository.Update(customer);
customerRepository.Delete(customer);
Console.WriteLine(
"\r\nEnd program - logging and authentication\r\n***");
Console.ReadLine();

}

Figure 12 The Main Program Calling


the Repository with Two Users


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

if (!methodInfo.Name.StartsWith("Get"))
Log("In Dynamic Proxy - Before executing '{0}'",
methodCall.MethodName);

try
{
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
if (!methodInfo.Name.StartsWith("Get"))
Log("In Dynamic Proxy - After executing '{0}' ",
methodCall.MethodName);

return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
catch (Exception e)
{
if (!methodInfo.Name.StartsWith("Get"))
Log(string.Format(
"In Dynamic Proxy- Exception {0} executing '{1}'", e),
methodCall.MethodName);
return new ReturnMessage(e, methodCall);
}
}

Figure 14 Filtering Methods for the Aspect


Figure 13 Output of the Program Using Two Proxies


pub lic class RepositoryFactory
{
public static IRepository<T> Create<T>()
{
var repository = new Repository<T>();
var decoratedRepository =
(IRepository<T>)new DynamicProxy<IRepository<T>>(
repository).GetTransparentProxy();
// Create a dynamic proxy for the class already decorated
decoratedRepository =
(IRepository<T>)new AuthenticationProxy<IRepository<T>>(
decoratedRepository).GetTransparentProxy();
return decoratedRepository;
}
}

Figure 11 The Repository Factory Decorated by Two Proxies

Free download pdf