上一篇:unity 2.0 interception 学习2
前面讲的是类型拦截,在类型拦截中,目标类型不是原始类型(被拦截的类),原始类型(被拦截的类)会被动态的派生,调用这个派生类的virtual方法实际会转移到behavior[0]的invoke方法。
今天看看实例拦截:
public static object ThroughProxyWithAdditionalInterfaces(
Type interceptedType,
object target,
IInstanceInterceptor interceptor,
IEnumerable<IInterceptionBehavior> interceptionBehaviors,
IEnumerable<Type> additionalInterfaces)
{
Guard.ArgumentNotNull(interceptedType, "interceptedType");
Guard.ArgumentNotNull(target, "target");
Guard.ArgumentNotNull(interceptor, "interceptor");
Guard.ArgumentNotNull(interceptionBehaviors, "interceptionBehaviors");
Guard.ArgumentNotNull(additionalInterfaces, "additionalInterfaces");
if (!interceptor.CanIntercept(interceptedType))
{
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Resources.InterceptionNotSupported,
interceptedType.FullName),
"interceptedType");
}
var behaviors = interceptionBehaviors.ToList();
if(behaviors.Where(ib => ib == null).Count() > 0)
{
throw new ArgumentException(
string.Format(CultureInfo.CurrentCulture, Resources.NullBehavior),
"interceptionBehaviors");
}
var activeBehaviors = behaviors.Where(ib => ib.WillExecute).ToList();
var allAdditionalInterfaces
= GetAllAdditionalInterfaces(activeBehaviors, additionalInterfaces).ToList();
// If no behaviors and no extra interfaces, nothing to do.
if(activeBehaviors.Count == 0 && allAdditionalInterfaces.Count == 0)
{
return target;
}
IInterceptingProxy proxy =
interceptor.CreateProxy(interceptedType, target, allAdditionalInterfaces.ToArray());
foreach (IInterceptionBehavior interceptionBehavior in activeBehaviors)
{
proxy.AddInterceptionBehavior(interceptionBehavior);
}
return proxy;
}
一、InterfaceInterceptor:
public IInterceptingProxy CreateProxy(Type t, object target, params Type[] additionalInterfaces)
{
Guard.ArgumentNotNull(t, "t");
Guard.ArgumentNotNull(additionalInterfaces, "additionalInterfaces");
Type interceptorType;
Type typeToProxy = t;
bool genericType = false;
if (t.IsGenericType)
{
typeToProxy = t.GetGenericTypeDefinition();
genericType = true;
}
GeneratedTypeKey key = new GeneratedTypeKey(typeToProxy, additionalInterfaces);
lock (interceptorClasses)
{
if (!interceptorClasses.TryGetValue(key, out interceptorType))
{
InterfaceInterceptorClassGenerator generator =
new InterfaceInterceptorClassGenerator(typeToProxy, additionalInterfaces);
interceptorType = generator.CreateProxyType();
interceptorClasses[key] = interceptorType;
}
}
if (genericType)
{
interceptorType = interceptorType.MakeGenericType(t.GetGenericArguments());
}
return (IInterceptingProxy)interceptorType.GetConstructors()[0].Invoke(new object[] { target, t });
}
我的目标是:为什么代理实例对方法的调用会转到target的调用上,即如何实现类似装饰模式的?