代理对象是通过以下代码来进行动态戴入.
switch (handlerField.Name) {
case mixinHandlerFieldName:
{
ilGenerator.Emit(OpCodes.Callvirt, typeof(IMixinInvocationHandler).GetMethod("Invoke") );
break;
}
default:
{
ilGenerator.Emit(OpCodes.Callvirt, typeof(IInvocationHandler).GetMethod("Invoke") );
break;
}
}
而IMixinInvocationHandler和IInvocationHandler接口的实现在代理对象的构造方法中中传入, 如下代码:
// class AspectSharpEngine
public static object Wrap(object target) {
Type originType = target.GetType();
string typeName = originType.FullName;
IInvocationHandler handler = GetInvocationHandler(target);
IMixinInvocationHandler mixinHandler = GetMixinInvocationHandler();
IMixin[] mixins = GetMixins(typeName);
// ...
return ProxyGenerator.CreateInstance( _typeCache[typeName], mixins, handler, mixinHandler );
}
同时传入代理对象构造方法的还有对象上的混合器接口.
这里IInvocationHandler的实现为DefaultInvocationHandler,
IMixinvocationHandler的实现为MixinInvocationHandler,
GetMixins从配置文件中获取加在对象上的所有混入器.
方法的截入过程:
1. 代理对象调用DefaultInvocationHandler.Invoke;
2. Invoke方法调用GetMethodInvocation通过配置文件来取得方法的拦截器;
IMethodInvocation GetMethodInvocation(MethodInfo method, object[] arguments) {
string typeName = _target.GetType().FullName;
IAspect aspect = GetAspectForType(typeName);
if(aspect != null && aspect.PointCuts != null) {
IMatch match = _methodMatcher.Match(method, aspect.PointCuts);
return new InterceptorMethodInvocation(_target, method, arguments, match.Interceptors);
// match.Interceptors为方法的所有载入点.
}
else {
return new DefaultMethodInvocation(_target, method, arguments);
}
}
这时有两种情况
a 方法没有定义截入点.
3. 建立一个DefaultMethodInvocation(默认的方法转发器);
4. 调用InvokeMethod执行真正的方法实现代码.
b. 方法有定义截入点.
3. 建立一个InterceptorMethodInvocation(拦截方法转发器);
4. 调用转发器的proceed方法;
// class IntreceptorMethodInvocation
public override object Proceed() {
if ( _currentInterceptorIndex == (_interceptors.Length - 1) ) {
return InvokeMethod(_target, _method, _arguments);
}
_currentInterceptorIndex++ ;
IInterceptor currentInterceptor = _interceptors[_currentInterceptorIndex];
if(currentInterceptor is IMethodInterceptor) {
return ((IMethodInterceptor)currentInterceptor).Invoke(this);
}
else {
return InvokeMethod(_target, _method, _arguments);
}
}
// 调用拦截器的Invoke方法, 然后执行真正方法的实现代码.
// 拦截器必须实现IMethodInterceptor接口.
此段代码只能调用_interceptors[0]的拦截器代码, 其它拦截器代码如何执行入?
答案在我们实现的拦截器中, 在拦截器中, 典型的Invoke代码如下:
public object Invoke(IMethodInvocation invocation) {
try {
// ...
return invocation.Proceed(); 这个是必须的, 这将使拦截过程继续下去.
}
catch(Exception e) {
// ...
}
return null;
}
混合器的混入过程
1. 调用MixinInvocationHandler.Invoke方法;
2. 通过DefaultInvocationHandler的GetTargetMethod取得混合器的方法.
3. 调用方法的实现代码.