From 67b6f8f2149255025a881de4c80c9b4190ea064a Mon Sep 17 00:00:00 2001 From: eeichinger Date: Mon, 23 Feb 2009 18:02:29 +0000 Subject: [PATCH] fixed SPRNET-1169 --- .../Spring.Aop/Aop/Framework/AopUtils.cs | 533 +++++++++--------- .../AutoProxy/AbstractAutoProxyCreator.cs | 145 +++-- .../Aop/Target/SingletonTargetSource.cs | 24 +- .../Framework/DynamicProxy/AopUtilsTests.cs | 30 +- .../Spring.Aop.Tests.2008.csproj | 1 + 5 files changed, 390 insertions(+), 343 deletions(-) diff --git a/src/Spring/Spring.Aop/Aop/Framework/AopUtils.cs b/src/Spring/Spring.Aop/Aop/Framework/AopUtils.cs index 257289ec..e089ed1b 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AopUtils.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AopUtils.cs @@ -1,5 +1,5 @@ -#region License - +#region License + /* * Copyright © 2002-2005 the original author or authors. * @@ -14,258 +14,279 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - -#endregion - -#region Imports - -using System; -using System.Reflection; -using Spring.Collections; -using Spring.Util; - -#endregion - -namespace Spring.Aop.Framework -{ - /// - /// Utility methods used by the AOP framework. - /// - /// - ///

- /// Not intended to be used directly by applications. - ///

- ///
- /// Rod Johnson - /// Juergen Hoeller - /// Aleksandar Seovic (.NET) - public sealed class AopUtils - { - - // This is a leaky abstraction as we have hardcoded known IAopProxyFactory implementations. - private const string COMPOSITION_PROXY_TYPE_NAME = "CompositionAopProxy"; - - private const string DECORATOR_PROXY_TYPE_NAME = "DecoratorAopProxy"; - - /// - /// Is the supplied an AOP proxy? - /// - /// - /// Return whether the given object is either - /// a composition-based proxy or a decorator-based proxy. - /// - /// The instance to be checked. - /// - /// if the supplied is - /// an AOP proxy. - /// - public static bool IsAopProxy(object instance) - { - return IsCompositionAopProxy(instance) || IsDecoratorAopProxy(instance); - } - - /// - /// Is the supplied a composition-based AOP proxy? - /// - /// The instance to be checked. - /// - /// if the supplied is - /// an composition-based AOP proxy. - /// - public static bool IsCompositionAopProxy(Object instance) - { - return ((instance != null) && instance.GetType().FullName.StartsWith(COMPOSITION_PROXY_TYPE_NAME)); - } - - /// - /// Is the supplied a decorator-based AOP proxy? - /// - /// The instance to be checked. - /// - /// if the supplied is - /// an decorator-based AOP proxy. - /// - public static bool IsDecoratorAopProxy(Object instance) - { - return ((instance != null) && instance.GetType().FullName.StartsWith(DECORATOR_PROXY_TYPE_NAME)); - } - - /// - /// Gets all of the interfaces that the of the - /// supplied implements. - /// - /// - ///

- /// This includes interfaces implemented by any superclasses. - ///

- ///
- /// - /// The object to analyse for interfaces. - /// - /// - /// All of the interfaces that the of the - /// supplied implements; or an empty - /// array if the supplied is - /// . - /// - public static Type[] GetAllInterfaces(object instance) - { - if (instance != null) - { - ISet interfaces = new HybridSet(); - Type type = instance.GetType(); - do - { - Type[] ifcs = type.GetInterfaces(); - foreach (Type ifc in ifcs) - { - interfaces.Add(ifc); - } - type = type.BaseType; - } while (type != null); - if (interfaces.Count > 0) - { - Type[] types = new Type[interfaces.Count]; - interfaces.CopyTo(types, 0); - return types; - } - } - return Type.EmptyTypes; - } - - /// - /// Can the supplied apply at all on the - /// supplied ? - /// - /// - ///

- /// This is an important test as it can be used to optimize out a - /// pointcut for a class. - ///

- ///

- /// Invoking this method with a that is - /// an interface type will always yield a - /// return value. - ///

- ///
- /// The pointcut being tested. - /// The class being tested. - /// - /// The interfaces being proxied. If , all - /// methods on a class may be proxied. - /// - /// - /// if the pointcut can apply on any method. - /// - public static bool CanApply( - IPointcut pointcut, Type targetType, Type[] proxyInterfaces) - { - if (!pointcut.TypeFilter.Matches(targetType)) - { - return false; - } - - // It may apply to the class - // Check whether it can apply on any method - // Checks public methods, including inherited methods - MethodInfo[] methods = targetType.GetMethods(); - for (int i = 0; i < methods.Length; ++i) - { - MethodInfo m = methods[i]; - // If we're looking only at interfaces and this method - // isn't on any of them, skip it - if (proxyInterfaces != null - && !ReflectionUtils.MethodIsOnOneOfTheseInterfaces(m, proxyInterfaces)) - { - continue; - } - if (pointcut.MethodMatcher.Matches(m, targetType)) - { - return true; - } - } - return false; - } - - /// - /// Can the supplied apply at all on the - /// supplied ? - /// - /// - ///

- /// This is an important test as it can be used to optimize out an - /// advisor for a class. - ///

- ///
- /// The advisor to check. - /// The class being tested. - /// - /// The interfaces being proxied. If , all - /// methods on a class may be proxied. - /// - /// - /// if the advisor can apply on any method. - /// - public static bool CanApply( - IAdvisor advisor, Type targetType, Type[] proxyInterfaces) - { - if (advisor is IIntroductionAdvisor) - { - return ((IIntroductionAdvisor) advisor).TypeFilter.Matches(targetType); - } - else if (advisor is IPointcutAdvisor) - { - IPointcutAdvisor pca = (IPointcutAdvisor) advisor; - return CanApply(pca.Pointcut, targetType, proxyInterfaces); - } - // no pointcut specified so assume it applies... - return true; - } - - #region Constructor (s) / Destructor - - // CLOVER:OFF - - /// - /// Creates a new instance of the - /// class. - /// - /// - ///

- /// This is a utility class, and as such has no publicly - /// visible constructors. - ///

- ///
- private AopUtils() - { - } - - // CLOVER:ON - - #endregion - - /// - /// Gets the type of the target. - /// - /// The candidate. - /// - public static Type GetTargetType(object candidate) - { - AssertUtils.ArgumentNotNull(candidate,"candidate", "Candidate object must not be null"); - if (candidate is ITargetSource) - { - return ((ITargetSource) candidate).TargetType; - } - if (candidate is IAdvised) - { - return ((IAdvised) candidate).TargetSource.TargetType; - } - if (IsDecoratorAopProxy(candidate)) - { - return candidate.GetType().BaseType; - } - return candidate.GetType(); - } - } + */ + +#endregion + +#region Imports + +using System; +using System.Reflection; +using Spring.Collections; +using Spring.Util; + +#endregion + +namespace Spring.Aop.Framework +{ + /// + /// Utility methods used by the AOP framework. + /// + /// + ///

+ /// Not intended to be used directly by applications. + ///

+ ///
+ /// Rod Johnson + /// Juergen Hoeller + /// Aleksandar Seovic (.NET) + public sealed class AopUtils + { + + // This is a leaky abstraction as we have hardcoded known IAopProxyFactory implementations. + private const string COMPOSITION_PROXY_TYPE_NAME = "CompositionAopProxy"; + + private const string DECORATOR_PROXY_TYPE_NAME = "DecoratorAopProxy"; + + /// + /// Is the supplied an AOP proxy? + /// + /// + /// Return whether the given object is either + /// a composition-based proxy or a decorator-based proxy. + /// + /// The instance to be checked. + /// + /// if the supplied is + /// an AOP proxy. + /// + public static bool IsAopProxy(object instance) + { + return IsCompositionAopProxy(instance) || IsDecoratorAopProxy(instance); + } + + /// + /// Is the supplied a composition-based AOP proxy? + /// + /// The instance to be checked. + /// + /// if the supplied is + /// an composition-based AOP proxy. + /// + public static bool IsCompositionAopProxy(Object instance) + { + return ((instance != null) && instance.GetType().FullName.StartsWith(COMPOSITION_PROXY_TYPE_NAME)); + } + + /// + /// Is the supplied a decorator-based AOP proxy? + /// + /// The instance to be checked. + /// + /// if the supplied is + /// an decorator-based AOP proxy. + /// + public static bool IsDecoratorAopProxy(Object instance) + { + return ((instance != null) && instance.GetType().FullName.StartsWith(DECORATOR_PROXY_TYPE_NAME)); + } + + /// + /// Gets all of the interfaces that the of the + /// supplied implements. + /// + /// + ///

+ /// This includes interfaces implemented by any superclasses. + ///

+ ///
+ /// + /// The object to analyse for interfaces. + /// + /// + /// All of the interfaces that the of the + /// supplied implements; or an empty + /// array if the supplied is + /// . + /// + public static Type[] GetAllInterfaces(object instance) + { + if (instance != null) + { + Type type = instance.GetType(); + return GetAllInterfacesFromType(type); + } + return Type.EmptyTypes; + } + + /// + /// Gets all of the interfaces that the + /// supplied implements. + /// + /// + /// This includes interfaces implemented by any superclasses. + /// + /// + /// The type to analyse for interfaces. + /// + /// + /// All of the interfaces that the supplied implements. + /// + public static Type[] GetAllInterfacesFromType(Type type) + { + AssertUtils.ArgumentNotNull(type, "type"); + ISet interfaces = new HybridSet(); + do + { + Type[] ifcs = type.GetInterfaces(); + foreach (Type ifc in ifcs) + { + interfaces.Add(ifc); + } + type = type.BaseType; + } while (type != null); + + if (interfaces.Count > 0) + { + Type[] types = new Type[interfaces.Count]; + interfaces.CopyTo(types, 0); + return types; + } + return Type.EmptyTypes; + } + + /// + /// Can the supplied apply at all on the + /// supplied ? + /// + /// + ///

+ /// This is an important test as it can be used to optimize out a + /// pointcut for a class. + ///

+ ///

+ /// Invoking this method with a that is + /// an interface type will always yield a + /// return value. + ///

+ ///
+ /// The pointcut being tested. + /// The class being tested. + /// + /// The interfaces being proxied. If , all + /// methods on a class may be proxied. + /// + /// + /// if the pointcut can apply on any method. + /// + public static bool CanApply( + IPointcut pointcut, Type targetType, Type[] proxyInterfaces) + { + if (!pointcut.TypeFilter.Matches(targetType)) + { + return false; + } + + // It may apply to the class + // Check whether it can apply on any method + // Checks public methods, including inherited methods + MethodInfo[] methods = targetType.GetMethods(); + for (int i = 0; i < methods.Length; ++i) + { + MethodInfo m = methods[i]; + // If we're looking only at interfaces and this method + // isn't on any of them, skip it + if (proxyInterfaces != null + && !ReflectionUtils.MethodIsOnOneOfTheseInterfaces(m, proxyInterfaces)) + { + continue; + } + if (pointcut.MethodMatcher.Matches(m, targetType)) + { + return true; + } + } + return false; + } + + /// + /// Can the supplied apply at all on the + /// supplied ? + /// + /// + ///

+ /// This is an important test as it can be used to optimize out an + /// advisor for a class. + ///

+ ///
+ /// The advisor to check. + /// The class being tested. + /// + /// The interfaces being proxied. If , all + /// methods on a class may be proxied. + /// + /// + /// if the advisor can apply on any method. + /// + public static bool CanApply( + IAdvisor advisor, Type targetType, Type[] proxyInterfaces) + { + if (advisor is IIntroductionAdvisor) + { + return ((IIntroductionAdvisor)advisor).TypeFilter.Matches(targetType); + } + else if (advisor is IPointcutAdvisor) + { + IPointcutAdvisor pca = (IPointcutAdvisor)advisor; + return CanApply(pca.Pointcut, targetType, proxyInterfaces); + } + // no pointcut specified so assume it applies... + return true; + } + + #region Constructor (s) / Destructor + + // CLOVER:OFF + + /// + /// Creates a new instance of the + /// class. + /// + /// + ///

+ /// This is a utility class, and as such has no publicly + /// visible constructors. + ///

+ ///
+ private AopUtils() + { + } + + // CLOVER:ON + + #endregion + + /// + /// Gets the type of the target. + /// + /// The candidate. + /// + public static Type GetTargetType(object candidate) + { + AssertUtils.ArgumentNotNull(candidate, "candidate", "Candidate object must not be null"); + if (candidate is ITargetSource) + { + return ((ITargetSource)candidate).TargetType; + } + if (candidate is IAdvised) + { + return ((IAdvised)candidate).TargetSource.TargetType; + } + if (IsDecoratorAopProxy(candidate)) + { + return candidate.GetType().BaseType; + } + return candidate.GetType(); + } + } } \ No newline at end of file diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs index a01dba61..8fe22aee 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs @@ -78,7 +78,7 @@ namespace Spring.Aop.Framework.AutoProxy /// /// The logger for this class hierarchy. /// - protected readonly ILog logger = LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType ); + protected readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); /// /// Convenience constant for subclasses: Return value for "do not proxy". @@ -128,11 +128,11 @@ namespace Spring.Aop.Framework.AutoProxy /// creator created a custom TargetSource for. Used to detect own pre-built proxies /// (from "PostProcessBeforeInstantiation") in the "PostProcessAfterInitialization" method. /// - private ISet targetSourcedObjects = new SynchronizedSet( new HashedSet() ); + private ISet targetSourcedObjects = new SynchronizedSet(new HashedSet()); - private ISet advisedObjects = new SynchronizedSet( new HashedSet() ); + private ISet advisedObjects = new SynchronizedSet(new HashedSet()); - private ISet nonAdvisedObjects = new SynchronizedSet( new HashedSet() ); + private ISet nonAdvisedObjects = new SynchronizedSet(new HashedSet()); #endregion @@ -224,69 +224,66 @@ namespace Spring.Aop.Framework.AutoProxy /// Create a proxy with the configured interceptors if the object is /// identified as one to proxy by the subclass. /// - public virtual object PostProcessAfterInitialization( object obj, string objectName ) + public virtual object PostProcessAfterInitialization(object obj, string objectName) { - if (targetSourcedObjects.Contains( objectName )) + if (targetSourcedObjects.Contains(objectName)) { return obj; } - object cacheKey = GetCacheKey( obj.GetType(), objectName ); - if (nonAdvisedObjects.Contains( cacheKey )) + Type objectType = RemotingServices.IsTransparentProxy(obj) + ? ObjectFactory.GetType(objectName) + : obj.GetType(); + + object cacheKey = GetCacheKey(objectType, objectName); + if (nonAdvisedObjects.Contains(cacheKey)) { return obj; } - if (IsInfrastructureType( obj.GetType(), objectName )) + if (IsInfrastructureType(objectType, objectName)) { #region Instrumentation if (logger.IsDebugEnabled) { - logger.Debug( string.Format( "Did not attempt to autoproxy infrastructure type [{0}]", obj.GetType() ) ); + logger.Debug(string.Format("Did not attempt to autoproxy infrastructure type [{0}]", objectType)); } #endregion - nonAdvisedObjects.Add( cacheKey ); + nonAdvisedObjects.Add(cacheKey); return obj; } - if (ShouldSkip( obj.GetType(), objectName )) + if (ShouldSkip(objectType, objectName)) { #region Instrumentation if (logger.IsDebugEnabled) { - logger.Debug( string.Format( "Skipping type [{0}]", obj.GetType() ) ); + logger.Debug(string.Format("Skipping type [{0}]", objectType)); } #endregion - nonAdvisedObjects.Add( cacheKey ); + nonAdvisedObjects.Add(cacheKey); return obj; } //ITargetSource targetSource = GetCustomTargetSource(obj.GetType(), objectName); object[] specificInterceptors; - if (RemotingServices.IsTransparentProxy( obj )) - { - specificInterceptors = GetAdvicesAndAdvisorsForObject( ObjectFactory.GetType( objectName ), objectName, null ); - } - else - { - specificInterceptors = GetAdvicesAndAdvisorsForObject( obj.GetType(), objectName, null ); - } + specificInterceptors = GetAdvicesAndAdvisorsForObject(objectType, objectName, null); // proxy if we have advice or if a TargetSourceCreator wants to do some // fancy stuff such as pooling if (specificInterceptors != DO_NOT_PROXY) { - advisedObjects.Add( cacheKey ); - return CreateProxy( obj.GetType(), objectName, specificInterceptors, new SingletonTargetSource( obj ) ); + advisedObjects.Add(cacheKey); + return CreateProxy(objectType, objectName, specificInterceptors, new SingletonTargetSource(obj, objectType)); } - nonAdvisedObjects.Add( cacheKey ); + nonAdvisedObjects.Add(cacheKey); return obj; } @@ -296,7 +293,7 @@ namespace Spring.Aop.Framework.AutoProxy /// The obj. /// The name. /// - public virtual object PostProcessBeforeInitialization( object obj, string name ) + public virtual object PostProcessBeforeInitialization(object obj, string name) { return obj; } @@ -361,7 +358,7 @@ namespace Spring.Aop.Framework.AutoProxy /// the type of the object /// the name of the object /// if remarkable to skip - protected virtual bool ShouldSkip( Type objectType, string objectName ) + protected virtual bool ShouldSkip(Type objectType, string objectName) { return false; } @@ -373,7 +370,7 @@ namespace Spring.Aop.Framework.AutoProxy /// /// ProxyFactory that will be used to create the proxy immediably after this method returns. /// - protected virtual void CustomizeProxyFactory( ProxyFactory pf ) + protected virtual void CustomizeProxyFactory(ProxyFactory pf) { // This implementation does nothing } @@ -387,12 +384,12 @@ namespace Spring.Aop.Framework.AutoProxy /// /// true if [is infrastructure type] [the specified obj]; otherwise, false. /// - protected virtual bool IsInfrastructureType( Type type, String name ) + protected virtual bool IsInfrastructureType(Type type, String name) { - return typeof( IAdvisor ).IsAssignableFrom( type ) - || typeof( IAdvice ).IsAssignableFrom( type ) - || typeof( IAdvisors ).IsAssignableFrom( type ) - || typeof( AbstractAutoProxyCreator ).IsAssignableFrom( type ); + return typeof(IAdvisor).IsAssignableFrom(type) + || typeof(IAdvice).IsAssignableFrom(type) + || typeof(IAdvisors).IsAssignableFrom(type) + || typeof(AbstractAutoProxyCreator).IsAssignableFrom(type); } @@ -406,22 +403,22 @@ namespace Spring.Aop.Framework.AutoProxy /// the type of the object to create a TargetSource for /// the name of the object /// a TargetSource for this object - protected virtual ITargetSource GetCustomTargetSource( Type objectType, string name ) + protected virtual ITargetSource GetCustomTargetSource(Type objectType, string name) { // We can't create fancy target sources for directly registered singletons. if (customTargetSourceCreators != null && - owningObjectFactory != null && owningObjectFactory.ContainsObject( name )) + owningObjectFactory != null && owningObjectFactory.ContainsObject(name)) { for (int i = 0; i < customTargetSourceCreators.Count; i++) { ITargetSourceCreator tsc = (ITargetSourceCreator)customTargetSourceCreators[i]; - ITargetSource ts = tsc.GetTargetSource( objectType, name, owningObjectFactory ); + ITargetSource ts = tsc.GetTargetSource(objectType, name, owningObjectFactory); if (ts != null) { // found a match if (logger.IsInfoEnabled) { - logger.Info( string.Format( "TargetSourceCreator [{0} found custom TargetSource for object with objectName '{1}'", tsc, name ) ); + logger.Info(string.Format("TargetSourceCreator [{0} found custom TargetSource for object with objectName '{1}'", tsc, name)); } return ts; } @@ -451,7 +448,7 @@ namespace Spring.Aop.Framework.AutoProxy /// an array of additional interceptors for the particular object; /// or an empty array if no additional interceptors but just the common ones; /// or null if no proxy at all, not even with the common interceptors. - protected abstract object[] GetAdvicesAndAdvisorsForObject( Type objType, string name, ITargetSource customTargetSource ); + protected abstract object[] GetAdvicesAndAdvisorsForObject(Type objType, string name, ITargetSource customTargetSource); /// /// Create an AOP proxy for the given object. @@ -462,11 +459,11 @@ namespace Spring.Aop.Framework.AutoProxy /// object (may be empty but not null) /// The target source for the proxy, already pre-configured to access the object. /// The AOP Proxy for the object. - protected virtual object CreateProxy( Type objectType, string objectName, object[] specificInterceptors, ITargetSource targetSource ) + protected virtual object CreateProxy(Type objectType, string objectName, object[] specificInterceptors, ITargetSource targetSource) { ProxyFactory proxyFactory = CreateProxyFactory(); // copy our properties (proxyTargetClass) inherited from ProxyConfig - proxyFactory.CopyFrom( this ); + proxyFactory.CopyFrom(this); object target = targetSource.GetTarget(); @@ -475,29 +472,29 @@ namespace Spring.Aop.Framework.AutoProxy { // Must allow for introductions; can't just set interfaces to // the target's interfaces only. - Type[] targetInterfaceTypes = AopUtils.GetAllInterfaces( target ); + Type[] targetInterfaceTypes = AopUtils.GetAllInterfacesFromType(objectType); foreach (Type interfaceType in targetInterfaceTypes) { - proxyFactory.AddInterface( interfaceType ); + proxyFactory.AddInterface(interfaceType); } } - IAdvisor[] advisors = BuildAdvisors( objectName, specificInterceptors ); + IAdvisor[] advisors = BuildAdvisors(objectName, specificInterceptors); foreach (IAdvisor advisor in advisors) { if (advisor is IIntroductionAdvisor) { - proxyFactory.AddIntroduction( (IIntroductionAdvisor)advisor ); + proxyFactory.AddIntroduction((IIntroductionAdvisor)advisor); } else { - proxyFactory.AddAdvisor( advisor ); + proxyFactory.AddAdvisor(advisor); } } proxyFactory.TargetSource = targetSource; - CustomizeProxyFactory( proxyFactory ); + CustomizeProxyFactory(proxyFactory); proxyFactory.IsFrozen = freezeProxy; return proxyFactory.GetProxy(); @@ -520,7 +517,7 @@ namespace Spring.Aop.Framework.AutoProxy /// The set of interceptors that is specific to this /// object (may be empty, but not null) /// The list of Advisors for the given object - protected virtual IAdvisor[] BuildAdvisors( string objectName, object[] specificInterceptors ) + protected virtual IAdvisor[] BuildAdvisors(string objectName, object[] specificInterceptors) { // handle prototypes correctly IAdvisor[] commonInterceptors = ResolveInterceptorNames(); @@ -528,16 +525,16 @@ namespace Spring.Aop.Framework.AutoProxy ArrayList allInterceptors = new ArrayList(); if (specificInterceptors != null) { - allInterceptors.AddRange( specificInterceptors ); + allInterceptors.AddRange(specificInterceptors); if (commonInterceptors != null) { if (applyCommonInterceptorsFirst) { - allInterceptors.InsertRange( 0, commonInterceptors ); + allInterceptors.InsertRange(0, commonInterceptors); } else { - allInterceptors.AddRange( commonInterceptors ); + allInterceptors.AddRange(commonInterceptors); } } } @@ -545,14 +542,14 @@ namespace Spring.Aop.Framework.AutoProxy { int nrOfCommonInterceptors = commonInterceptors != null ? commonInterceptors.Length : 0; int nrOfSpecificInterceptors = specificInterceptors != null ? specificInterceptors.Length : 0; - logger.Info( string.Format( "Creating implicit proxy for object '{0}' with {1} common interceptors and {2} specific interceptors", objectName, nrOfCommonInterceptors, nrOfSpecificInterceptors ) ); + logger.Info(string.Format("Creating implicit proxy for object '{0}' with {1} common interceptors and {2} specific interceptors", objectName, nrOfCommonInterceptors, nrOfSpecificInterceptors)); } IAdvisor[] advisors = new IAdvisor[allInterceptors.Count]; for (int i = 0; i < allInterceptors.Count; i++) { - advisors[i] = advisorAdapterRegistry.Wrap( allInterceptors[i] ); + advisors[i] = advisorAdapterRegistry.Wrap(allInterceptors[i]); } return advisors; } @@ -563,7 +560,7 @@ namespace Spring.Aop.Framework.AutoProxy /// The object type. /// The object name. /// The cache key for the given type and name - protected virtual object GetCacheKey( Type objectType, string objectName ) + protected virtual object GetCacheKey(Type objectType, string objectName) { return objectType.FullName + "_" + objectName; } @@ -578,17 +575,17 @@ namespace Spring.Aop.Framework.AutoProxy ArrayList advisors = new ArrayList(); foreach (string name in interceptorNames) { - object next = owningObjectFactory.GetObject( name ); + object next = owningObjectFactory.GetObject(name); if (next is IAdvisors) { - advisors.AddRange( ((IAdvisors)next).Advisors ); + advisors.AddRange(((IAdvisors)next).Advisors); } else { - advisors.Add( advisorAdapterRegistry.Wrap( next ) ); + advisors.Add(advisorAdapterRegistry.Wrap(next)); } } - return (IAdvisor[])advisors.ToArray( typeof( IAdvisor ) ); + return (IAdvisor[])advisors.ToArray(typeof(IAdvisor)); } #endregion @@ -601,55 +598,55 @@ namespace Spring.Aop.Framework.AutoProxy /// The object type /// The object name /// null if not creating a proxy, otherwise return the proxy. - public object PostProcessBeforeInstantiation( Type objectType, string objectName ) + public object PostProcessBeforeInstantiation(Type objectType, string objectName) { - object cacheKey = GetCacheKey( objectType, objectName ); - if (!targetSourcedObjects.Contains( cacheKey )) + object cacheKey = GetCacheKey(objectType, objectName); + if (!targetSourcedObjects.Contains(cacheKey)) { - if (advisedObjects.Contains( cacheKey ) || nonAdvisedObjects.Contains( cacheKey )) + if (advisedObjects.Contains(cacheKey) || nonAdvisedObjects.Contains(cacheKey)) { return null; } - if (IsInfrastructureType( objectType, objectName )) + if (IsInfrastructureType(objectType, objectName)) { #region Instrumentation if (logger.IsDebugEnabled) { - logger.Debug( string.Format( "Did not attempt to autoproxy infrastructure type [{0}]", objectType ) ); + logger.Debug(string.Format("Did not attempt to autoproxy infrastructure type [{0}]", objectType)); } #endregion - nonAdvisedObjects.Add( cacheKey ); + nonAdvisedObjects.Add(cacheKey); return null; } - if (ShouldSkip( objectType, objectName )) + if (ShouldSkip(objectType, objectName)) { #region Instrumentation if (logger.IsDebugEnabled) { - logger.Debug( string.Format( "Skipping type [{0}]", objectType ) ); + logger.Debug(string.Format("Skipping type [{0}]", objectType)); } #endregion - nonAdvisedObjects.Add( cacheKey ); + nonAdvisedObjects.Add(cacheKey); return null; } } // Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target object: // The TargetSource will handle target instances in a custom fashion. - ITargetSource targetSource = GetCustomTargetSource( objectType, objectName ); + ITargetSource targetSource = GetCustomTargetSource(objectType, objectName); if (targetSource != null) { - targetSourcedObjects.Add( objectName ); - object[] specificInterceptors = GetAdvicesAndAdvisorsForObject( objectType, objectName, targetSource ); - return CreateProxy( objectType, objectName, specificInterceptors, targetSource ); + targetSourcedObjects.Add(objectName); + object[] specificInterceptors = GetAdvicesAndAdvisorsForObject(objectType, objectName, targetSource); + return CreateProxy(objectType, objectName, specificInterceptors, targetSource); } return null; } @@ -661,7 +658,7 @@ namespace Spring.Aop.Framework.AutoProxy /// The object instance /// The object name. /// true - public bool PostProcessAfterInstantiation( object objectInstance, string objectName ) + public bool PostProcessAfterInstantiation(object objectInstance, string objectName) { return true; } @@ -676,8 +673,8 @@ namespace Spring.Aop.Framework.AutoProxy /// been set. /// Name of the object. /// The passed in PropertyValues - public IPropertyValues PostProcessPropertyValues( IPropertyValues pvs, PropertyInfo[] pis, object objectInstance, - string objectName ) + public IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, PropertyInfo[] pis, object objectInstance, + string objectName) { return pvs; } diff --git a/src/Spring/Spring.Aop/Aop/Target/SingletonTargetSource.cs b/src/Spring/Spring.Aop/Aop/Target/SingletonTargetSource.cs index 66c58617..99d80bf6 100644 --- a/src/Spring/Spring.Aop/Aop/Target/SingletonTargetSource.cs +++ b/src/Spring/Spring.Aop/Aop/Target/SingletonTargetSource.cs @@ -44,7 +44,8 @@ namespace Spring.Aop.Target [Serializable] public sealed class SingletonTargetSource : ITargetSource { - private object target; + private object target; + private Type targetType; /// /// Creates a new instance of the @@ -57,9 +58,26 @@ namespace Spring.Aop.Target /// . /// public SingletonTargetSource(object target) + :this(target, target != null ? target.GetType() : null) + {} + + /// + /// Creates a new instance of the + /// + /// for the specified target object. + /// + /// The target object to expose. + /// The type of to expose. + /// + /// If the supplied is + /// . + /// + public SingletonTargetSource(object target, Type targetType) { AssertUtils.ArgumentNotNull(target, "target"); - this.target = target; + AssertUtils.ArgumentNotNull(targetType, "targetType"); + this.target = target; + this.targetType = targetType; } #region ITarget Source impl @@ -69,7 +87,7 @@ namespace Spring.Aop.Target /// public Type TargetType { - get { return target.GetType(); } + get { return targetType; } } /// diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/DynamicProxy/AopUtilsTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/DynamicProxy/AopUtilsTests.cs index dcb05b9c..f69ef490 100644 --- a/test/Spring/Spring.Aop.Tests/Aop/Framework/DynamicProxy/AopUtilsTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/DynamicProxy/AopUtilsTests.cs @@ -43,16 +43,6 @@ namespace Spring.Aop.Framework.DynamicProxy [TestFixture] public sealed class AopUtilsTests { - [Test] - public void GetAllInterfaces() - { - DerivedTestObject testObject = new DerivedTestObject(); - IList interfaces = new ArrayList(testObject.GetType().GetInterfaces()); - Assert.AreEqual(9, interfaces.Count, "Incorrect number of interfaces"); - Assert.IsTrue(interfaces.Contains(typeof (ITestObject)), "Does not contain ITestObject"); - Assert.IsTrue(interfaces.Contains(typeof (IOther)), "Does not contain IOther"); - } - [Test] public void PointcutCanNeverApply() { @@ -103,6 +93,19 @@ namespace Spring.Aop.Framework.DynamicProxy Assert.IsTrue(AopUtils.CanApply((IAdvisor) null, typeof (TestObject), null)); } + /// + /// Test preconditions for all tests related to GetAllInterfaces + /// + [Test] + public void GetAllInterfacesTestsPreconditions() + { + DerivedTestObject testObject = new DerivedTestObject(); + IList interfaces = new ArrayList(testObject.GetType().GetInterfaces()); + Assert.AreEqual(9, interfaces.Count, "Incorrect number of interfaces"); + Assert.IsTrue(interfaces.Contains(typeof(ITestObject)), "Does not contain ITestObject"); + Assert.IsTrue(interfaces.Contains(typeof(IOther)), "Does not contain IOther"); + } + [Test] public void GetAllInterfacesWithNull() { @@ -113,6 +116,13 @@ namespace Spring.Aop.Framework.DynamicProxy "Must return an empty array is the argument is null."); } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void GetAllInterfacesFromTypeWithNull() + { + AopUtils.GetAllInterfacesFromType(null); + } + [Test] public void GetAllInterfacesWithObjectThatDoesntImpementAnything() { 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 153b74f4..1a03e27a 100644 --- a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj +++ b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj @@ -123,6 +123,7 @@ Code +