diff --git a/src/Spring/Spring.Aop/Aop/Framework/AdvisedSupport.cs b/src/Spring/Spring.Aop/Aop/Framework/AdvisedSupport.cs index 4a9eeaf8..dedd5209 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AdvisedSupport.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AdvisedSupport.cs @@ -76,7 +76,7 @@ namespace Spring.Aop.Framework /// Array updated on changes to the advisors list, which is easier to /// manipulate internally /// - private IAdvisor[] _advisorsArray = new IAdvisor[] {}; + private volatile IAdvisor[] _advisorsArray = new IAdvisor[] { }; /// /// List of introductions. @@ -88,7 +88,7 @@ namespace Spring.Aop.Framework /// manipulate internally /// private IIntroductionAdvisor[] _introductionsArray - = new IIntroductionAdvisor[] {}; + = new IIntroductionAdvisor[] { }; /// /// Interface map specifying which object should interface methods be @@ -100,7 +100,7 @@ namespace Spring.Aop.Framework /// to the target object. ///

/// - private IDictionary interfaceMap = new ListDictionary(); + private readonly IDictionary interfaceMap = new ListDictionary(); /// /// The for this instance. @@ -120,7 +120,7 @@ namespace Spring.Aop.Framework /// /// The list of event listeners. /// - private IList listeners = new ArrayList(); + private readonly IList listeners = new ArrayList(); /// /// The advisor chain factory. @@ -149,7 +149,8 @@ namespace Spring.Aop.Framework /// /// If this /// - public AdvisedSupport(Type[] interfaces) : this() + public AdvisedSupport(Type[] interfaces) + : this() { if (interfaces != null) { @@ -181,14 +182,14 @@ namespace Spring.Aop.Framework { get { - lock(this.SyncRoot) + lock (this.SyncRoot) { return this.advisorChainFactory; } } set { - lock(this.SyncRoot) + lock (this.SyncRoot) { if (this.advisorChainFactory != null) { @@ -216,12 +217,12 @@ namespace Spring.Aop.Framework { 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); } } @@ -240,23 +241,31 @@ namespace Spring.Aop.Framework get { bool canBeSerialized = TargetSource.TargetType.IsSerializable; - if (canBeSerialized) + if (!canBeSerialized) return false; + + lock (this.SyncRoot) { - for (int i = 0; canBeSerialized && i < _advisorsArray.Length; i++) + IAdvisor[] advisorsArray = this._advisorsArray; + IIntroductionAdvisor[] introductionsArray = this._introductionsArray; + + for (int i = 0; i < advisorsArray.Length; i++) { - IAdvisor advisor = _advisorsArray[i]; + IAdvisor advisor = advisorsArray[i]; canBeSerialized = advisor.GetType().IsSerializable && advisor.Advice.GetType().IsSerializable; + if (!canBeSerialized) return false; } - for (int i = 0; canBeSerialized && i < _introductionsArray.Length; i++) + + for (int i = 0; i < introductionsArray.Length; i++) { - IIntroductionAdvisor advisor = _introductionsArray[i]; + IIntroductionAdvisor advisor = introductionsArray[i]; canBeSerialized = advisor.GetType().IsSerializable && advisor.Advice.GetType().IsSerializable; + if (!canBeSerialized) return false; } } - return canBeSerialized; + return true; } } @@ -273,7 +282,7 @@ namespace Spring.Aop.Framework { get { - lock(this.SyncRoot) + lock (this.SyncRoot) { Type[] proxiedInterfaces = new Type[this.interfaceMap.Keys.Count]; this.interfaceMap.Keys.CopyTo(proxiedInterfaces, 0); @@ -282,7 +291,7 @@ namespace Spring.Aop.Framework } set { - lock(this.SyncRoot) + lock (this.SyncRoot) { this.interfaceMap.Clear(); for (int i = 0; i < value.Length; i++) @@ -307,7 +316,7 @@ namespace Spring.Aop.Framework { get { - lock(this.SyncRoot) + lock (this.SyncRoot) { return new Hashtable(this.interfaceMap); } @@ -332,7 +341,7 @@ namespace Spring.Aop.Framework { if (intf != null) { - lock(this.SyncRoot) + lock (this.SyncRoot) { foreach (Type proxyInterface in this.interfaceMap.Keys) { @@ -359,9 +368,10 @@ namespace Spring.Aop.Framework { get { - lock(this.SyncRoot) + // lock(this.SyncRoot) { - return (IAdvisor[]) this._advisorsArray.Clone(); + // return (IAdvisor[]) _advisorsArray.Clone(); + return _advisorsArray; } } } @@ -387,9 +397,9 @@ namespace Spring.Aop.Framework { get { - lock(this.SyncRoot) + lock (this.SyncRoot) { - return (IIntroductionAdvisor[]) this._introductionsArray.Clone(); + return (IIntroductionAdvisor[])this._introductionsArray.Clone(); } } } @@ -461,7 +471,7 @@ namespace Spring.Aop.Framework /// public virtual int IndexOf(IAdvisor advisor) { - lock(this.SyncRoot) + lock (this.SyncRoot) { return IndexOfInternal(advisor); } @@ -482,7 +492,7 @@ namespace Spring.Aop.Framework /// public virtual int IndexOf(IIntroductionAdvisor advisor) { - lock(this.SyncRoot) + lock (this.SyncRoot) { return IndexOfInternal(advisor); } @@ -509,7 +519,7 @@ namespace Spring.Aop.Framework bool wasRemoved = false; if (advisor != null) { - lock(this.SyncRoot) + lock (this.SyncRoot) { int index = IndexOf(advisor); if (index == -1) @@ -545,7 +555,7 @@ namespace Spring.Aop.Framework public virtual void RemoveAdvisor(int index) { DieIfFrozen("Cannot remove advisor: config is frozen"); - lock(this.SyncRoot) + lock (this.SyncRoot) { RemoveAdvisorInternal(index); } @@ -569,7 +579,7 @@ namespace Spring.Aop.Framework /// public bool RemoveAdvice(IAdvice advice) { - lock(this.SyncRoot) + lock (this.SyncRoot) { int index = IndexOf(advice); if (index == -1) @@ -606,7 +616,7 @@ namespace Spring.Aop.Framework bool wasRemoved = false; if (introduction != null) { - lock(this.SyncRoot) + lock (this.SyncRoot) { int index = IndexOf(introduction); if (index == -1) @@ -639,7 +649,7 @@ namespace Spring.Aop.Framework public virtual void RemoveIntroduction(int index) { DieIfFrozen("Cannot remove introduction: config is frozen"); - lock(this.SyncRoot) + lock (this.SyncRoot) { if (index < 0 || index >= _introductions.Count) { @@ -647,7 +657,7 @@ namespace Spring.Aop.Framework "Introduction index " + index + " is out of bounds: Only have " + _introductions.Count + " introductions."); } - IIntroductionAdvisor advisor = (IIntroductionAdvisor) _introductions[index]; + IIntroductionAdvisor advisor = (IIntroductionAdvisor)_introductions[index]; // remove all interfaces introduced by the advisor... foreach (Type intf in advisor.Interfaces) { @@ -658,33 +668,33 @@ namespace Spring.Aop.Framework } } -// -// /// -// /// Removes the supplied from the list of -// /// for this -// /// proxy. -// /// -// /// -// /// The to be removed. -// /// -// /// -// /// If this proxy configuration is frozen and the -// /// cannot be added. -// /// -// public bool RemoveInterceptor(IInterceptor interceptor) -// { -// AssertFrozen("Cannot remove interceptor: config is frozen"); -// int index = IndexOf(interceptor); -// if (index == -1) -// { -// return false; -// } -// else -// { -// RemoveAdvisor(index); -// return true; -// } -// } + // + // /// + // /// Removes the supplied from the list of + // /// for this + // /// proxy. + // /// + // /// + // /// The to be removed. + // /// + // /// + // /// If this proxy configuration is frozen and the + // /// cannot be added. + // /// + // public bool RemoveInterceptor(IInterceptor interceptor) + // { + // AssertFrozen("Cannot remove interceptor: config is frozen"); + // int index = IndexOf(interceptor); + // if (index == -1) + // { + // return false; + // } + // else + // { + // RemoveAdvisor(index); + // return true; + // } + // } /// /// Adds the supplied to the list @@ -705,12 +715,12 @@ namespace Spring.Aop.Framework public virtual void AddAdvisor(int index, IAdvisor advisor) { DieIfFrozen("Cannot add advisor: config is frozen"); - lock(this.SyncRoot) + lock (this.SyncRoot) { // advisor already in list (SPRNET-846) if (_advisors.Contains(advisor)) return; - if(index == -1) + if (index == -1) { this._advisors.Add(advisor); } @@ -756,7 +766,7 @@ namespace Spring.Aop.Framework { if (advisor is IIntroductionAdvisor) { - AddIntroduction((IIntroductionAdvisor) advisor); + AddIntroduction((IIntroductionAdvisor)advisor); } else { @@ -786,7 +796,7 @@ namespace Spring.Aop.Framework DieIfFrozen("Cannot add introduction: config is frozen"); introductionAdvisor.ValidateInterfaces(); - lock(this.SyncRoot) + lock (this.SyncRoot) { if (index < this._introductions.Count) { @@ -822,13 +832,13 @@ namespace Spring.Aop.Framework public virtual void AddIntroduction(IIntroductionAdvisor introductionAdvisor) { Type introductionType = introductionAdvisor.Advice.GetType(); - lock(this.SyncRoot) + lock (this.SyncRoot) { int pos = this._introductions.Count; for (int i = 0; i < pos; i++) { IIntroductionAdvisor introduction - = (IIntroductionAdvisor) this._introductions[i]; + = (IIntroductionAdvisor)this._introductions[i]; if (introduction.Advice.GetType() == introductionType) { pos = i; @@ -858,14 +868,14 @@ namespace Spring.Aop.Framework /// public virtual void ReplaceIntroduction(int index, IIntroductionAdvisor introduction) { - lock(this.SyncRoot) + lock (this.SyncRoot) { - if(index < 0 || index >= _introductions.Count) + if (index < 0 || index >= _introductions.Count) { throw new AopConfigException( "Introduction index " + index + " is out of bounds:" + " there are currently " + _introductions.Count + - " introductions." ); + " introductions."); } _introductions[index] = introduction; @@ -897,7 +907,7 @@ namespace Spring.Aop.Framework public bool ReplaceAdvisor(IAdvisor oldAdvisor, IAdvisor newAdvisor) { DieIfFrozen("Cannot replace advisor: config is frozen."); - lock(this.SyncRoot) + lock (this.SyncRoot) { int index = IndexOf(oldAdvisor); if (index == -1 || newAdvisor == null) @@ -920,7 +930,7 @@ namespace Spring.Aop.Framework /// public virtual string ToProxyConfigString() { - lock(this.SyncRoot) + lock (this.SyncRoot) { return ToStringInternal(); } @@ -1016,7 +1026,7 @@ namespace Spring.Aop.Framework /// public virtual void AddListener(IAdvisedSupportListener listener) { - lock(this.SyncRoot) + lock (this.SyncRoot) { this.listeners.Add(listener); } @@ -1031,7 +1041,7 @@ namespace Spring.Aop.Framework /// public virtual void RemoveListener(IAdvisedSupportListener listener) { - lock(this.SyncRoot) + lock (this.SyncRoot) { this.listeners.Remove(listener); } @@ -1052,10 +1062,10 @@ namespace Spring.Aop.Framework /// public virtual void AddInterface(Type intf) { - DieIfFrozen("Cannot add interface: configuration is frozen."); + DieIfFrozen("Cannot add interface: configuration is frozen."); AssertUtils.ArgumentNotNull(intf, "intf", "Cannot proxy a null interface."); - lock(this.SyncRoot) + lock (this.SyncRoot) { AddInterfaceInternal(intf); InterfacesChanged(); @@ -1090,8 +1100,8 @@ namespace Spring.Aop.Framework /// if the interface was removed. public virtual bool RemoveInterface(Type intf) { - DieIfFrozen("Cannot remove interface: configuration is frozen."); - lock(this.SyncRoot) + DieIfFrozen("Cannot remove interface: configuration is frozen."); + lock (this.SyncRoot) { if (intf != null && this.interfaceMap.Contains(intf)) { @@ -1125,7 +1135,7 @@ namespace Spring.Aop.Framework /// public virtual int IndexOf(IAdvice advice) { - lock(this.SyncRoot) + lock (this.SyncRoot) { return IndexOfInternal(advice); } @@ -1158,7 +1168,7 @@ namespace Spring.Aop.Framework { for (int i = 0; i < this._advisors.Count; ++i) { - IAdvisor advisor = (IAdvisor) this._advisors[i]; + IAdvisor advisor = (IAdvisor)this._advisors[i]; if (advisor.Advice == advice) { return i; @@ -1275,7 +1285,7 @@ namespace Spring.Aop.Framework public int CountAdviceOfType(Type interceptorType) { int count = 0; - lock(this.SyncRoot) + lock (this.SyncRoot) { foreach (IAdvisor advisor in this._advisors) { @@ -1313,8 +1323,9 @@ namespace Spring.Aop.Framework /// private void UpdateAdvisorsArray() { - this._advisorsArray = new IAdvisor[this._advisors.Count]; - this._advisors.CopyTo(this._advisorsArray, 0); + IAdvisor[] advisorsArray = new IAdvisor[this._advisors.Count]; + this._advisors.CopyTo(advisorsArray, 0); + this._advisorsArray = advisorsArray; } /// @@ -1322,8 +1333,9 @@ namespace Spring.Aop.Framework /// private void UpdateIntroductionsArray() { - this._introductionsArray = new IIntroductionAdvisor[this._introductions.Count]; - this._introductions.CopyTo(this._introductionsArray, 0); + IIntroductionAdvisor[] introductionsArray = new IIntroductionAdvisor[this._introductions.Count]; + this._introductions.CopyTo(introductionsArray, 0); + this._introductionsArray = introductionsArray; } /// @@ -1454,7 +1466,7 @@ namespace Spring.Aop.Framework /// public override string ToString() { - lock(this.SyncRoot) + lock (this.SyncRoot) { return ToStringInternal(); } diff --git a/src/Spring/Spring.Aop/Aop/Framework/AopContext.cs b/src/Spring/Spring.Aop/Aop/Framework/AopContext.cs index 2e8e5629..35d73830 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AopContext.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AopContext.cs @@ -20,6 +20,7 @@ #region Imports +using System; using System.Collections; using Spring.Threading; @@ -40,11 +41,17 @@ namespace Spring.Aop.Framework /// advice can use this to make advised calls. They can also use it to find /// advice configuration. ///

- /// + ///

+ /// To expose the current proxy, set the + /// property on the controlling proxy to . + /// The default value for the property + /// is , for performance reasons. + ///

+ /// /// The AOP framework does not expose proxies by default, as there is a /// performance cost in doing so. /// - ///

+ ///

/// The functionality in this class might be used by a target object that /// needed access to resources on the invocation. However, this approach /// should not be used when there is a reasonable alternative, as it makes @@ -56,34 +63,21 @@ namespace Spring.Aop.Framework /// Aleksandar Seovic (.NET) public sealed class AopContext { - private const string CURRENTPROXY_SLOTNAME = "AopContext.CurrentProxySlotName"; + [ThreadStatic] + private static Stack tls_ProxyStack; ///

- /// The AOP proxy associated with this thread. + /// The AOP proxy stack associated with this thread. /// - /// - ///

- /// Will be unless the - /// property - /// on the controlling proxy has been set to . - ///

- ///

- /// The default value for the - /// property - /// is , for performance reasons. - ///

- ///
private static Stack ProxyStack { get { - Stack proxyStack = LogicalThreadContext.GetData(CURRENTPROXY_SLOTNAME) as Stack; - if (proxyStack == null) + if (tls_ProxyStack == null) { - proxyStack = new Stack(); - LogicalThreadContext.SetData(CURRENTPROXY_SLOTNAME, proxyStack); + tls_ProxyStack = new Stack(); } - return proxyStack; + return tls_ProxyStack; } } @@ -106,8 +100,7 @@ namespace Spring.Aop.Framework { get { - Stack proxyStack = LogicalThreadContext.GetData(CURRENTPROXY_SLOTNAME) as Stack; - return (proxyStack != null && proxyStack.Count > 0); + return (tls_ProxyStack != null && tls_ProxyStack.Count > 0); } } @@ -121,13 +114,14 @@ namespace Spring.Aop.Framework { get { - if (ProxyStack.Count == 0) + Stack proxyStack = ProxyStack; + if (proxyStack.Count == 0) { throw new AopConfigException( "Cannot find proxy: Set the 'ExposeProxy' property " + "to 'true' on IAdvised to make it available."); } - return ProxyStack.Peek(); + return proxyStack.Peek(); } } @@ -163,12 +157,13 @@ namespace Spring.Aop.Framework /// public static void PopProxy() { - if (ProxyStack.Count == 0) + Stack proxyStack = ProxyStack; + if (proxyStack.Count == 0) { throw new AopConfigException( "Proxy stack empty. Always call 'PushProxy' before 'PopProxy'."); } - ProxyStack.Pop(); + proxyStack.Pop(); } #region Constructor (s) / Destructor diff --git a/src/Spring/Spring.Aop/Aop/Framework/HashtableCachingAdvisorChainFactory.cs b/src/Spring/Spring.Aop/Aop/Framework/HashtableCachingAdvisorChainFactory.cs index 1714ed8b..074719ea 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/HashtableCachingAdvisorChainFactory.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/HashtableCachingAdvisorChainFactory.cs @@ -22,82 +22,84 @@ using System; using System.Collections; +using System.Collections.Specialized; using System.Reflection; +using Spring.Collections; #endregion namespace Spring.Aop.Framework { - /// - /// implementation - /// that caches advisor chains on a per-advised-method basis. - /// - /// Rod Johnson - /// Aleksandar Seovic (.NET) - [Serializable] - public sealed class HashtableCachingAdvisorChainFactory : IAdvisorChainFactory - { - private IDictionary methodCache = new Hashtable(); - - /// - /// Gets the list of and - /// - /// instances for the supplied . - /// - /// The proxy configuration object. - /// The object proxy. - /// - /// The method for which the interceptors are to be evaluated. - /// - /// - /// The of the target object. - /// - /// - /// The list of and - /// - /// instances for the supplied . - /// - public IList GetInterceptors(IAdvised advised, object proxy, MethodInfo method, Type targetType) - { - IList cached = (IList) this.methodCache[method]; - if (cached == null) - { - // recalculate... - cached = AdvisorChainFactoryUtils.CalculateInterceptors(advised, proxy, method, targetType); + /// + /// implementation + /// that caches advisor chains on a per-advised-method basis. + /// + /// Rod Johnson + /// Aleksandar Seovic (.NET) + [Serializable] + public sealed class HashtableCachingAdvisorChainFactory : IAdvisorChainFactory + { + private readonly IDictionary methodCache = new ListDictionary(); + + /// + /// Gets the list of and + /// + /// instances for the supplied . + /// + /// The proxy configuration object. + /// The object proxy. + /// + /// The method for which the interceptors are to be evaluated. + /// + /// + /// The of the target object. + /// + /// + /// The list of and + /// + /// instances for the supplied . + /// + public IList GetInterceptors(IAdvised advised, object proxy, MethodInfo method, Type targetType) + { + IList cached = (IList)this.methodCache[method]; + if (cached == null) + { + // recalculate... + cached = AdvisorChainFactoryUtils.CalculateInterceptors(advised, proxy, method, targetType); this.methodCache[method] = cached; - } - return cached; - } + } + return cached; + } - /// - /// Invoked when the first proxy is created. - /// - /// - /// The relevant source. - /// - public void Activated(AdvisedSupport source) - { - } + /// + /// Invoked when the first proxy is created. + /// + /// + /// The relevant source. + /// + public void Activated(AdvisedSupport source) + { + } - /// - /// Invoked when advice is changed after a proxy is created. - /// - /// - /// The relevant source. - /// - public void AdviceChanged(AdvisedSupport source) - { - methodCache.Clear(); - } + /// + /// Invoked when advice is changed after a proxy is created. + /// + /// + /// The relevant source. + /// + public void AdviceChanged(AdvisedSupport source) + { + methodCache.Clear(); + } - /// - /// Invoked when interfaces are changed after a proxy is created. - /// - /// - /// The relevant source. - /// - public void InterfacesChanged(AdvisedSupport source) - { - } - } + /// + /// Invoked when interfaces are changed after a proxy is created. + /// + /// + /// The relevant source. + /// + public void InterfacesChanged(AdvisedSupport source) + { + } + } } \ No newline at end of file diff --git a/src/Spring/Spring.Aop/Aop/Framework/ProxyConfig.cs b/src/Spring/Spring.Aop/Aop/Framework/ProxyConfig.cs index 0a145c4a..eda0c092 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/ProxyConfig.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/ProxyConfig.cs @@ -59,7 +59,7 @@ namespace Spring.Aop.Framework private IAopProxyFactory aopProxyFactory = ObjectUtils.InstantiateType( typeof(ProxyConfig).Assembly, "Spring.Aop.Framework.DynamicProxy.CachedAopProxyFactory") as IAopProxyFactory; private bool exposeProxy; - private object syncRoot = new object(); + private readonly object syncRoot = new object(); #endregion #region Properites diff --git a/src/Spring/Spring.Core/Reflection/Dynamic/DynamicMethod.cs b/src/Spring/Spring.Core/Reflection/Dynamic/DynamicMethod.cs index 221dc15d..d5a51fbf 100644 --- a/src/Spring/Spring.Core/Reflection/Dynamic/DynamicMethod.cs +++ b/src/Spring/Spring.Core/Reflection/Dynamic/DynamicMethod.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2007 the original author or authors. + * Copyright © 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,9 @@ using System; using System.Collections; +using System.Collections.Specialized; using System.Reflection; -using System.Reflection.Emit; +using Spring.Collections; using Spring.Util; #endregion @@ -79,29 +80,23 @@ namespace Spring.Reflection.Dynamic #if NET_2_0 #region Generated Function Cache - private static readonly IDictionary methodCache = new Hashtable(); - - /// - /// Obtains cached property info or creates a new entry, if none is found. - /// - private static FunctionDelegate GetOrCreateDynamicMethod(MethodInfo methodInfo) + private class SafeMethodState { - FunctionDelegate method = (FunctionDelegate)methodCache[methodInfo]; - if (method == null) + public readonly FunctionDelegate method; + public readonly object[] nullArguments; + + public SafeMethodState(FunctionDelegate method, object[] nullArguments) { - method = DynamicReflectionManager.CreateMethod(methodInfo); - lock (methodCache) - { - methodCache[methodInfo] = method; - } + this.method = method; + this.nullArguments = nullArguments; } - return method; - } + } + + private static readonly IDictionary stateCache = new HybridDictionary(); #endregion - private readonly FunctionDelegate method; - private readonly object[] nullArguments; + private readonly SafeMethodState state; /// /// Creates a new instance of the safe method wrapper. @@ -111,9 +106,15 @@ namespace Spring.Reflection.Dynamic { AssertUtils.ArgumentNotNull(methodInfo, "You cannot create a dynamic method for a null value."); + state = (SafeMethodState)stateCache[methodInfo]; + if (state == null) + { + state = new SafeMethodState(DynamicReflectionManager.CreateMethod(methodInfo), + new object[methodInfo.GetParameters().Length] + ); + stateCache[methodInfo] = state; + } this.methodInfo = methodInfo; - this.method = GetOrCreateDynamicMethod(methodInfo); - this.nullArguments = new object[methodInfo.GetParameters().Length]; } /// @@ -131,14 +132,15 @@ namespace Spring.Reflection.Dynamic public object Invoke(object target, params object[] arguments) { // special case - when calling Invoke(null,null) it is undecidible if the second null is an argument or the argument array - if (arguments==null && nullArguments.Length==1) arguments=nullArguments; - int arglen = (arguments==null?0:arguments.Length); - AssertUtils.IsTrue( - nullArguments.Length == arglen - , string.Format("Invalid number of arguments passed into method {0} - expected {1}, but was {2}", methodInfo.Name, nullArguments.Length, arglen) - ); + object[] nullArguments = state.nullArguments; + if (arguments == null && nullArguments.Length == 1) arguments = nullArguments; + int arglen = (arguments == null ? 0 : arguments.Length); + if (nullArguments.Length != arglen) + { + throw new ArgumentException(string.Format("Invalid number of arguments passed into method {0} - expected {1}, but was {2}", methodInfo.Name, nullArguments.Length, arglen)); + } - return this.method(target, arguments); + return this.state.method(target, arguments); } #else private IDynamicMethod dynamicMethod; @@ -206,7 +208,7 @@ namespace Spring.Reflection.Dynamic } #endregion - + #if NET_2_0 /// /// Factory class for dynamic methods. @@ -263,7 +265,7 @@ namespace Spring.Reflection.Dynamic private static readonly CreateMethodCallback s_createMethodCallback = new CreateMethodCallback(CreateInternal); - #region Create Method + #region Create Method /// /// Creates dynamic method instance for the specified . diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/AopContextTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/AopContextTests.cs index 96be81bd..71e59468 100644 --- a/test/Spring/Spring.Aop.Tests/Aop/Framework/AopContextTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/AopContextTests.cs @@ -22,7 +22,7 @@ using System; using System.Threading; - +using AopAlliance.Aop; using NUnit.Framework; using Spring.Objects; @@ -34,58 +34,58 @@ using Spring.Util; namespace Spring.Aop.Framework { - /// - /// Unit tests for the AopContext class. - /// - /// Rick Evans - [TestFixture] - public sealed class AopContextTests - { - [SetUp] - public void SetUp() - { - // makes sure the context is always empty before any unit test... - try - { - do - { - AopContext.PopProxy(); - } while (true); - } - catch (AopConfigException) - { - } - } - - [Test] - [ExpectedException(typeof (AopConfigException))] - public void CurrentProxyChokesIfNoAopProxyIsOnTheStack() - { - AopContext.CurrentProxy.ToString(); - } - - [Test] - public void CurrentProxyStackJustPeeksItDoesntPop() - { - string foo = "Foo"; - AopContext.PushProxy(foo); - object fooref = AopContext.CurrentProxy; - Assert.IsTrue(ReferenceEquals(foo, fooref), - "Not the exact same instance (must be)."); - // must not have been popped off the stack by looking at it... - object foorefref = AopContext.CurrentProxy; - Assert.IsTrue(ReferenceEquals(fooref, foorefref), - "Not the exact same instance (must be)."); - } - - [Test] - [ExpectedException(typeof (AopConfigException))] - public void PopProxyWithNothingOnStack() - { - AopContext.PopProxy(); + /// + /// Unit tests for the AopContext class. + /// + /// Rick Evans + [TestFixture] + public sealed class AopContextTests + { + [SetUp] + public void SetUp() + { + // makes sure the context is always empty before any unit test... + try + { + do + { + AopContext.PopProxy(); + } while (true); + } + catch (AopConfigException) + { + } } [Test] + [ExpectedException(typeof(AopConfigException))] + public void CurrentProxyChokesIfNoAopProxyIsOnTheStack() + { + AopContext.CurrentProxy.ToString(); + } + + [Test] + public void CurrentProxyStackJustPeeksItDoesntPop() + { + string foo = "Foo"; + AopContext.PushProxy(foo); + object fooref = AopContext.CurrentProxy; + Assert.IsTrue(ReferenceEquals(foo, fooref), + "Not the exact same instance (must be)."); + // must not have been popped off the stack by looking at it... + object foorefref = AopContext.CurrentProxy; + Assert.IsTrue(ReferenceEquals(fooref, foorefref), + "Not the exact same instance (must be)."); + } + + [Test] + [ExpectedException(typeof(AopConfigException))] + public void PopProxyWithNothingOnStack() + { + AopContext.PopProxy(); + } + + [Test(Description = "SPRNET-1158")] public void IsActiveMatchesStackState() { Assert.IsFalse(AopContext.IsActive); @@ -97,11 +97,72 @@ namespace Spring.Aop.Framework #region CurrentProxyIsThreadSafe + [Test, Explicit] + public void ProxyPerformanceTests() + { + int runs = 5000000; + StopWatch watch = new StopWatch(); + + ITestObject testObject = new ChainableTestObject(null); + using (watch.Start("Naked Duration: {0}")) + { + for (int i = 0; i < runs; i++) + { + object result = testObject.DoSomething(this); + } + } + + ITestObject hardcodedWrapper = new ChainableTestObject(testObject); + using (watch.Start("Hardcoded Wrapper Duration: {0}")) + { + for (int i = 0; i < runs; i++) + { + object result = hardcodedWrapper.DoSomething(this); + } + } + + PeformanceTestAopContextInterceptor interceptor = new PeformanceTestAopContextInterceptor(); + ITestObject proxy = CreateProxy(testObject, interceptor, false); + using(watch.Start("Proxy Duration ('ExposeProxy'==false): {0}")) + { + for(int i=0;i