From 0882e83fe3985ebcc00389f40acfab9cc3c1bf3a Mon Sep 17 00:00:00 2001 From: eeichinger Date: Sun, 27 Sep 2009 16:48:37 +0000 Subject: [PATCH] polishing --- common-project.include | 2 +- .../Aop/Framework/AdvisedSupport.cs | 36 +++----- .../DynamicProxy/AbstractAopProxyFactory.cs | 90 +++++++++++++++++++ .../DynamicProxy/BaseCompositionAopProxy.cs | 5 -- .../CompositionAopProxyTypeBuilder.cs | 2 +- .../DynamicProxy/DefaultAopProxyFactory.cs | 53 ++--------- .../Aop/Target/SingletonTargetSource.cs | 4 +- src/Spring/Spring.Aop/Spring.Aop.2008.csproj | 1 + .../Spring.Core/Expressions/Expression.cs | 56 ++++++++++-- .../Proxy/AbstractProxyMethodBuilder.cs | 14 ++- .../DynamicProxy/AbstractAopProxyTests.cs | 2 + .../Spring.Aop.Tests.2008.csproj | 3 +- 12 files changed, 170 insertions(+), 98 deletions(-) create mode 100644 src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/AbstractAopProxyFactory.cs diff --git a/common-project.include b/common-project.include index 6e82dc08..2ce5feeb 100644 --- a/common-project.include +++ b/common-project.include @@ -185,7 +185,7 @@ ${tool.dir} : dir for tools --> - + diff --git a/src/Spring/Spring.Aop/Aop/Framework/AdvisedSupport.cs b/src/Spring/Spring.Aop/Aop/Framework/AdvisedSupport.cs index 38697132..052e2ddc 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AdvisedSupport.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AdvisedSupport.cs @@ -243,18 +243,6 @@ namespace Spring.Aop.Framework set { m_targetSource= (value != null) ? value : EmptyTargetSource.Empty; -// TODO (EE):remove -// bool initialized = !(this.m_targetSource is EmptyTargetSource); -// this.m_targetSource = value; -// -// if (this.m_targetSource != null && !initialized && interfaceMap.Count == 0) -// { -// Type[] interfaces = ReflectionUtils.GetInterfaces(this.m_targetSource.TargetType); -// foreach (Type intf in interfaces) -// { -// AddInterfaceInternal(intf); -// } -// } } } @@ -963,22 +951,18 @@ namespace Spring.Aop.Framework #endregion - #region ITargetTypeAware implementation - - /// - /// Gets the target type behind the implementing object. - /// Ttypically a proxy configuration or an actual proxy. - /// - /// The type of the target or null if not known. - public Type TargetType - { - get { return TargetSource.TargetType; } - } - - #endregion - #region Properties + /// + /// Gets the target type behind the implementing object. + /// Ttypically a proxy configuration or an actual proxy. + /// + /// The type of the target or null if not known. + public Type TargetType + { + get { return TargetSource.TargetType; } + } + /// /// If no explicit interfaces are specified, interfaces will be automatically determined /// from the target type on proxy creation. Defaults to true diff --git a/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/AbstractAopProxyFactory.cs b/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/AbstractAopProxyFactory.cs new file mode 100644 index 00000000..8ff91c56 --- /dev/null +++ b/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/AbstractAopProxyFactory.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections; +using Spring.Aop.Support; +using Spring.Aop.Target; + +namespace Spring.Aop.Framework.DynamicProxy +{ + /// + /// A reusable base implementation of , providing + /// some useful default implementations + /// + /// Erich Eichinger + [Serializable] + public abstract class AbstractAopProxyFactory : IAopProxyFactory + { + /// + /// Creates an for the + /// supplied configuration. + /// + /// The AOP configuration. + /// An . + /// + /// If the supplied configuration is + /// invalid. + /// + /// + public IAopProxy CreateAopProxy(AdvisedSupport advisedSupport) + { + if (advisedSupport == null) + { + throw new AopConfigException("Cannot create IAopProxy with null ProxyConfig"); + } + if (advisedSupport.Advisors.Length == 0 && advisedSupport.TargetSource == EmptyTargetSource.Empty) + { + throw new AopConfigException("Cannot create IAopProxy with no advisors and no target source"); + } + + EliminateDuplicateAdvisors(advisedSupport); + + return DoCreateAopProxyInstance(advisedSupport); + } + + /// + /// Actually creates the proxy instance based on the supplied . + /// + /// the proxy instance described by . Must not be null + protected abstract IAopProxy DoCreateAopProxyInstance(AdvisedSupport advisedSupport); + + /// + /// If possible, checks for advisor duplicates on the supplied and + /// eliminates them. + /// + protected virtual void EliminateDuplicateAdvisors(AdvisedSupport advisedSupport) + { + if (advisedSupport.TargetSource is SingletonTargetSource + && IsAopProxyType(advisedSupport.TargetSource)) + { + IAdvised innerProxy = (IAdvised)advisedSupport.TargetSource.GetTarget(); + // eliminate duplicate advisors + ArrayList thisAdvisors = new ArrayList(advisedSupport.Advisors); + foreach (IAdvisor innerAdvisor in innerProxy.Advisors) + { + foreach (IAdvisor thisAdvisor in thisAdvisors) + { + if (ReferenceEquals(thisAdvisor, innerAdvisor) + || (thisAdvisor.GetType() == typeof(DefaultPointcutAdvisor) + && ((DefaultPointcutAdvisor)thisAdvisor).Equals(innerAdvisor) + ) + ) + { + advisedSupport.RemoveAdvisor(thisAdvisor); + } + } + } + + // elimination of duplicate introductions is not necessary + // since they do not propagate to nested proxy anyway + } + } + + /// + /// Checks, if the given holds a proxy generated by this factory. + /// + /// + protected virtual bool IsAopProxyType(ITargetSource targetSource) + { + return AopUtils.IsAopProxyType(targetSource.TargetType); + } + } +} \ No newline at end of file diff --git a/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/BaseCompositionAopProxy.cs b/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/BaseCompositionAopProxy.cs index e53490db..f10a59d3 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/BaseCompositionAopProxy.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/BaseCompositionAopProxy.cs @@ -94,11 +94,6 @@ namespace Spring.Aop.Framework.DynamicProxy /// true if the specified Object is equal to the current target object; otherwise, false public override bool Equals(object obj) { -// if (ReferenceEquals(this, obj)) -// { -// return true; -// } - AdvisedProxy otherProxy = obj as AdvisedProxy; if (otherProxy != null) { diff --git a/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/CompositionAopProxyTypeBuilder.cs b/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/CompositionAopProxyTypeBuilder.cs index 90de5483..1d6023f0 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/CompositionAopProxyTypeBuilder.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/CompositionAopProxyTypeBuilder.cs @@ -43,7 +43,7 @@ namespace Spring.Aop.Framework.DynamicProxy private const string PROXY_TYPE_NAME = "CompositionAopProxy"; - private IAdvised advised; + private readonly IAdvised advised; #endregion diff --git a/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/DefaultAopProxyFactory.cs b/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/DefaultAopProxyFactory.cs index 9c7b8d8c..b4fc6dd5 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/DefaultAopProxyFactory.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/DynamicProxy/DefaultAopProxyFactory.cs @@ -19,11 +19,8 @@ #endregion using System; -using System.Collections; using System.Reflection; -using Spring.Aop.Support; using Spring.Proxy; -using Spring.Aop.Target; using Spring.Util; namespace Spring.Aop.Framework.DynamicProxy @@ -51,7 +48,7 @@ namespace Spring.Aop.Framework.DynamicProxy /// Erich Eichinger (.NET) /// [Serializable] - public class DefaultAopProxyFactory : IAopProxyFactory + public class DefaultAopProxyFactory : AbstractAopProxyFactory { /// /// Force transient assemblies to be resolvable by . @@ -62,26 +59,12 @@ namespace Spring.Aop.Framework.DynamicProxy } /// - /// Creates an for the - /// supplied configuration. + /// Creates an actual proxy instance based on the supplied /// - /// The AOP configuration. - /// An . - /// - /// If the supplied configuration is - /// invalid. - /// - /// - public virtual IAopProxy CreateAopProxy(AdvisedSupport advisedSupport) + /// + /// + protected override IAopProxy DoCreateAopProxyInstance(AdvisedSupport advisedSupport) { - if (advisedSupport == null) - { - throw new AopConfigException("Cannot create IAopProxy with null ProxyConfig"); - } - if (advisedSupport.Advisors.Length == 0 && advisedSupport.TargetSource == EmptyTargetSource.Empty) - { - throw new AopConfigException("Cannot create IAopProxy with no advisors and no target source"); - } if (advisedSupport.ProxyType == null) { IProxyTypeBuilder typeBuilder; @@ -97,32 +80,6 @@ namespace Spring.Aop.Framework.DynamicProxy advisedSupport.ProxyType = BuildProxyType(typeBuilder); advisedSupport.ProxyConstructor = advisedSupport.ProxyType.GetConstructor(new Type[] { typeof(IAdvised) }); } - - if (advisedSupport.TargetSource is SingletonTargetSource - && AopUtils.IsAopProxyType(advisedSupport.TargetSource.TargetType)) - { - IAdvised innerProxy = (IAdvised)advisedSupport.TargetSource.GetTarget(); - // eliminate duplicate advisors - ArrayList thisAdvisors = new ArrayList(advisedSupport.Advisors); - foreach (IAdvisor innerAdvisor in innerProxy.Advisors) - { - foreach (IAdvisor thisAdvisor in thisAdvisors) - { - if (ReferenceEquals(thisAdvisor, innerAdvisor) - || (thisAdvisor.GetType() == typeof(DefaultPointcutAdvisor) - && ((DefaultPointcutAdvisor)thisAdvisor).Equals(innerAdvisor) - ) - ) - { - advisedSupport.RemoveAdvisor(thisAdvisor); - } - } - } - - // elimination of duplicate introductions is not necessary - // since they do not propagate to nested proxy anyway - } - return (IAopProxy)advisedSupport.ProxyConstructor.Invoke(new object[] { advisedSupport }); } diff --git a/src/Spring/Spring.Aop/Aop/Target/SingletonTargetSource.cs b/src/Spring/Spring.Aop/Aop/Target/SingletonTargetSource.cs index 99d80bf6..73b33175 100644 --- a/src/Spring/Spring.Aop/Aop/Target/SingletonTargetSource.cs +++ b/src/Spring/Spring.Aop/Aop/Target/SingletonTargetSource.cs @@ -44,8 +44,8 @@ namespace Spring.Aop.Target [Serializable] public sealed class SingletonTargetSource : ITargetSource { - private object target; - private Type targetType; + private readonly object target; + private readonly Type targetType; /// /// Creates a new instance of the diff --git a/src/Spring/Spring.Aop/Spring.Aop.2008.csproj b/src/Spring/Spring.Aop/Spring.Aop.2008.csproj index 8d35e15e..7a8760d0 100644 --- a/src/Spring/Spring.Aop/Spring.Aop.2008.csproj +++ b/src/Spring/Spring.Aop/Spring.Aop.2008.csproj @@ -141,6 +141,7 @@ + diff --git a/src/Spring/Spring.Core/Expressions/Expression.cs b/src/Spring/Spring.Core/Expressions/Expression.cs index 22aebae1..286e56c8 100644 --- a/src/Spring/Spring.Core/Expressions/Expression.cs +++ b/src/Spring/Spring.Core/Expressions/Expression.cs @@ -27,6 +27,7 @@ using Spring.Expressions.Parser; using Spring.Expressions.Parser.antlr; using Spring.Expressions.Parser.antlr.collections; using Spring.Core; +using Spring.Reflection.Dynamic; using Spring.Util; using StringUtils = Spring.Util.StringUtils; @@ -63,14 +64,57 @@ namespace Spring.Expressions internal static readonly string CurrentObjectFactory = RESERVEDPREFIX + "CurrentObjectFactory"; } + private class ASTNodeCreator : Parser.antlr.ASTNodeCreator + { + private readonly SafeConstructor ctor; + private readonly string name; + + public ASTNodeCreator(ConstructorInfo ctor) + { + this.ctor = new SafeConstructor(ctor); + this.name = ctor.DeclaringType.FullName; + } + + public override AST Create() + { + return (AST) ctor.Invoke(new object[0]); + } + + public override string ASTNodeTypeName + { + get { return name; } + } + } + private class SpringASTFactory : ASTFactory { - public SpringASTFactory( Type t ) - : base( t.FullName ) + private static readonly Type BASENODE_TYPE; + private static readonly Hashtable Typename2Creator; + + static SpringASTFactory() { - base.defaultASTNodeTypeObject_ = t; - base.typename2creator_ = new Hashtable( 32, 0.3f ); - base.typename2creator_[t.FullName] = SpringAST.Creator; + BASENODE_TYPE = typeof (SpringAST); + + Typename2Creator = new Hashtable(); + foreach (Type type in typeof(SpringASTFactory).Assembly.GetTypes()) + { + if (BASENODE_TYPE.IsAssignableFrom(type)) + { + ConstructorInfo ctor = type.GetConstructor(new Type[0]); + if (ctor != null) + { + ASTNodeCreator creator = new ASTNodeCreator(ctor); + Typename2Creator[creator.ASTNodeTypeName] = creator; + } + } + } + Typename2Creator[BASENODE_TYPE.FullName] = SpringAST.Creator; + } + + public SpringASTFactory() : base(BASENODE_TYPE) + { + base.defaultASTNodeTypeObject_ = BASENODE_TYPE; + base.typename2creator_ = Typename2Creator; } } @@ -79,7 +123,7 @@ namespace Spring.Expressions public SpringExpressionParser( TokenStream lexer ) : base( lexer ) { - base.astFactory = new SpringASTFactory( typeof( SpringAST ) ); + base.astFactory = new SpringASTFactory(); base.initialize(); } } diff --git a/src/Spring/Spring.Core/Proxy/AbstractProxyMethodBuilder.cs b/src/Spring/Spring.Core/Proxy/AbstractProxyMethodBuilder.cs index 0694d39a..ea1c3788 100644 --- a/src/Spring/Spring.Core/Proxy/AbstractProxyMethodBuilder.cs +++ b/src/Spring/Spring.Core/Proxy/AbstractProxyMethodBuilder.cs @@ -266,11 +266,9 @@ namespace Spring.Proxy /// Calls target method directly. /// /// The IL generator to use. - /// - /// The interface definition of the method, if applicable. - /// + /// The method to invoke. protected virtual void CallDirectTargetMethod( - ILGenerator il, MethodInfo interfaceMethod) + ILGenerator il, MethodInfo targetMethod) { // setup target object for call PushTarget(il); @@ -279,21 +277,21 @@ namespace Spring.Proxy LocalBuilder targetRef = il.DeclareLocal(typeof(object)); il.Emit(OpCodes.Stloc, targetRef); - CallAssertUnderstands(il, interfaceMethod, targetRef, "target"); + CallAssertUnderstands(il, targetMethod, targetRef, "target"); // setup target and cast to type method is on il.Emit(OpCodes.Ldloc, targetRef); - il.Emit(OpCodes.Castclass, interfaceMethod.DeclaringType); + il.Emit(OpCodes.Castclass, targetMethod.DeclaringType); // setup parameters for call - ParameterInfo[] paramArray = interfaceMethod.GetParameters(); + ParameterInfo[] paramArray = targetMethod.GetParameters(); for (int i = 0; i < paramArray.Length; i++) { il.Emit(OpCodes.Ldarg_S, i + 1); } // call method - il.EmitCall(OpCodes.Callvirt, interfaceMethod, null); + il.EmitCall(OpCodes.Callvirt, targetMethod, null); } /// diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/DynamicProxy/AbstractAopProxyTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/DynamicProxy/AbstractAopProxyTests.cs index 15f680f7..8786ca3c 100644 --- a/test/Spring/Spring.Aop.Tests/Aop/Framework/DynamicProxy/AbstractAopProxyTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/DynamicProxy/AbstractAopProxyTests.cs @@ -847,6 +847,8 @@ namespace Spring.Aop.Framework.DynamicProxy CreateProxy(advised) as AbstractProxyTypeBuilderTests.InterfaceWithGenericMethod; Assert.IsNotNull(proxy); + DynamicProxyManager.SaveAssembly(); + proxy.PolymorphicMethod(); proxy.PolymorphicMethod(); diff --git a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj index 2cd269af..cbb37276 100644 --- a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj +++ b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj @@ -32,7 +32,8 @@ TRACE;DEBUG;NET_2_0;DEBUG_DYNAMIC - Spring.Aop.Tests.xml + + true 4096 false