Nick Parker
My ramblings on .NET...

Design by Contract with AOP Revisited

Wednesday, 19 October 2005 20:43 by nickp
Last night I posted a quick example of how we could place runtime requirements on methods. This is a common need by developers. I have since updated my example to clean it up a bit and make it more useable. The cleanup should make it much more extensible. In this example, I am placing two restrictions on our parameter. In order to call our function, the parameter being passed to it must be within both the minimum and maximum range defined in our PrologAttribute. What are your thoughts?

 

using System;
using
System.Reflection;
using
AopAlliance.Intercept;
using
Spring.Aop.Framework;
using
Spring.Aop.Interceptor;
using
Microsoft.VisualStudio.TestTools.UnitTesting;

namespace
DeveloperNotes
{
public class ConstraintInterceptor : IMethodInterceptor
{
public object Invoke(IMethodInvocation invocation)
{
MethodInfo mi
= invocation.Method;
if
(mi != null)
{
Object[] attrs
= mi.GetCustomAttributes(typeof(PrologAttribute), true);
if
(attrs != null && attrs.Length > 0)
{
bool results = false;
foreach
(PrologAttribute pl in attrs)
{
if (pl != null)
{
IEvaluator eval
= pl.Evaluator as IEvaluator;
if
(eval != null)
{
object[] args = invocation.Arguments;
results = eval.Evaluate(args[pl.Index]);
if
(!results)
break;
else
continue;
}
}
}
if(results)
return invocation.Proceed();
else
return null;
}
else
{
return invocation.Proceed();
}
}
return null;
}
}

public interface IEvaluator
{
bool Evaluate(object arg);
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple
=true, Inherited=true)]
public class PrologAttribute : Attribute
{
private int index;
public
IEvaluator evaluator;

public
PrologAttribute() { }

public PrologAttribute(int index, Type evalType, params object[] args)
{
this.Index = index;
Object obj = Activator.CreateInstance(evalType, args);
if
(obj != null)
this.evaluator = obj as IEvaluator;
}

public IEvaluator Evaluator
{
get { return evaluator; }
set { evaluator = value; }
}

public int Index
{
get { return index; }
set { index = value; }
}

public bool Evaluate(object arg)
{
return evaluator.Evaluate(arg);
}
}

public class StringLengthEvaluator : IEvaluator
{
private int min = 0;
private int
max = 0;

public
StringLengthEvaluator(int min, int max)
{
this.min = min;
this
.max = max;
}

public bool Evaluate(object arg)
{
int len = arg.ToString().Length;
return
(len <= max) && (len >= min);
}
}

public class ObjectFactory
{
public static K CreateObject<T, K>()
{
T obj
= Activator.CreateInstance<T>();
if
(obj != null)
{
ProxyFactory factory
= new ProxyFactory(obj);
factory.AddAdvice(new ConstraintInterceptor());
return
(K)factory.GetProxy();
}
return default(K);
}
}

public interface IPerson
{
void SayHello(string name);
}

public class Person : IPerson
{

[Prolog(
0, typeof(StringLengthEvaluator), 0, 5)]
public void SayHello(string name)
{
Console.WriteLine(
"Hello {0}", name);
}
}

class Program
{
static void Main(string[] args)
{
IPerson p
= ObjectFactory.CreateObject<Person, IPerson>();
if
(p != null)
{
p.SayHello(
"Nicholas");
p.SayHello("Nick");
}
Console.Read()
;
}
}
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories:   .NET | Design Patterns | AOP
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Design by Contract with AOP

Wednesday, 19 October 2005 01:00 by nickp
Over a year ago I discussed with Joe Duffy, a program manager on the CLR team about the concept of design by contract. Recently I had a similar disucussion with Richard Hale Shaw and Cyrus Najmabadi a developer on the C# compiler team at Microsoft while I was at the MVP Global Summit. I thought I would put together a quick example of how this could be applied, spawning off of my previous post discussing AOP. This example allows the developer to place certain restrictions on a method and for those restrictions to be applied before the method is actually called. In this example, if those restrictions aren't meet, the method is not called. If you step through the code, you will notice the second call to SayHello does not get called. Since this is simply an example, there is a lot that could change with this. For one, we would want to include the concept of an EpilogAttribute which would allow the developer to place constraints on the return value of the method as well. I'm curious what others think of something like this?

 

using System;
using
System.Reflection;
using
AopAlliance.Intercept;
using
Spring.Aop.Framework;
using
Spring.Aop.Interceptor;
using
Microsoft.VisualStudio.TestTools.UnitTesting;

namespace
DeveloperNotes
{
public class ConstraintInterceptor : IMethodInterceptor
{
public object Invoke(IMethodInvocation invocation)
{
MethodInfo mi
= invocation.Method;
if
(mi != null)
{
Object[] attrs
= mi.GetCustomAttributes(typeof(PrologAttribute), true);
if
(attrs != null && attrs.Length > 0)
{
PrologAttribute pl
= attrs[0] as PrologAttribute;
if
(pl != null)
{
object[] args = invocation.Arguments;
if
(args != null)
{
bool results = !Assert.Equals(args[pl.Index], pl.RVal);
if
(results)
return invocation.Proceed();
else
return null;
}
}
}
else
{
return invocation.Proceed();
}
}
return null;
}
}

public class PrologAttribute : Attribute
{
public int Index;
public object
RVal;

public
PrologAttribute() { }

public PrologAttribute(int index, object rval)
{
this.RVal = rval;
}
}

public class ObjectFactory
{
public static K CreateObject()
{
T obj
= Activator.CreateInstance();
if
(obj != null)
{
ProxyFactory factory
= new ProxyFactory(obj);
factory.AddAdvice(new ConstraintInterceptor());
return
(K)factory.GetProxy();
}
return default(K);
}
}

public interface IPerson
{
void SayHello(string name);
}

public class Person : IPerson
{

[Prolog(
0, "")]
public void SayHello(string name)
{
Console.WriteLine(
"Hello {0}", name);
}
}

class Program
{
static void Main(string[] args)
{
IPerson p
= ObjectFactory.CreateObject();
if
(p != null)
{
p.SayHello(
"Nick");
p.SayHello("Nicholas");
}
Console.Read()
;
}
}
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories:   .NET | Design Patterns | AOP
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Aspect Oriented Programming with Spring and Generics

Wednesday, 28 September 2005 02:56 by nickp
I wanted to post this example to flesh out an idea I was thinking about earlier today. Suppose you wanted to check permissions of a user before they made a method call, you might suggest an implementation of code access security. While that's a fair suggestion, I'd like to throw another option into the mix. With aspect oriented programming using the Spring framework, you can effectively check permissions before a method is called through the use of a proxy object that dispatches your calls to interceptors, that subsuquently invoke the requested call. Thus, depending on the results of your permission check, you can decide if you want to call the requested method or not. Here is a quick example implemented with generics. In the example, within the SecurityInterceptor you would check permissions which would allow you to control the Proceed call of the IMethodInvocation interface. Thoughts?

using System;
using
AopAlliance.Intercept;
using
Spring.Aop.Framework;
using
Spring.Aop.Interceptor;

namespace
DeveloperNotes
{
public class SecurityInterceptor : IMethodInterceptor
{

public object Invoke(IMethodInvocation invocation)
{
Console.WriteLine(
"Before: invocation=[{0}]", invocation);
object
rval = invocation.Proceed();
Console.WriteLine("Invocation returned");
return
rval;
}
}

public class ObjectFactory
{
public static K CreateObject<T, K>()
{
T obj
= Activator.CreateInstance<T>();
if
(obj != null)
{
ProxyFactory factory
= new ProxyFactory(obj);
factory.AddAdvice(new SecurityInterceptor());
return
(K)factory.GetProxy();
}
return default(K);
}
}

public interface IPerson
{
string Name
{
get;
set;
}

void SayHello();
}

public class Person : IPerson
{

private string name = string.Empty;

public string
Name
{
get{return name;}
set{name = value;}
}

public void SayHello()
{
Console.WriteLine(
"Hello {0}", this.Name);
}
}

class Program
{
static void Main(string[] args)
{
IPerson p
= ObjectFactory.CreateObject<Person, IPerson>();
if
(p != null)
{
p.Name
= "Nick";
p.SayHello();
}
Console.Read()
;
}
}
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories:   .NET | AOP | Design Patterns
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed