diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs
index ed1be482..a01dba61 100644
--- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs
+++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs
@@ -1,5 +1,5 @@
-#region License
-
+#region License
+
/*
* Copyright © 2002-2005 the original author or authors.
*
@@ -14,633 +14,674 @@
* 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.Collections;
-using System.Reflection;
-using System.Runtime.Remoting;
-using AopAlliance.Aop;
-using Common.Logging;
-using Spring.Aop.Framework.Adapter;
-using Spring.Aop.Target;
-using Spring.Collections;
-using Spring.Core;
-using Spring.Objects;
-using Spring.Objects.Factory;
-using Spring.Objects.Factory.Config;
-using Spring.Util;
-
-#endregion
-
-namespace Spring.Aop.Framework.AutoProxy
-{
- ///
- /// ObjectPostProcessor implementation that wraps a group of objects with AOP proxies
- /// that delegate to the given interceptors before invoking the object itself.
- ///
- ///
- /// This class distinguishes between "common" interceptors: shared for all proxies it
- /// creates, and "specific" interceptors: unique per object instance. There need not
- /// be any common interceptors. If there are, they are set using the interceptorNames
- /// property. As with ProxyFactoryObject, interceptors names in the current factory
- /// are used rather than object references to allow correct handling of prototype
- /// advisors and interceptors: for example, to support stateful mixins.
- /// Any advice type is supported for "interceptorNames" entries.
- /// Such autoproxying is particularly useful if there's a large number of objects that need
- /// to be wrapped with similar proxies, i.e. delegating to the same interceptors.
- /// Instead of x repetitive proxy definitions for x target objects, you can register
- /// one single such post processor with the object factory to achieve the same effect.
- /// Subclasses can apply any strategy to decide if a object is to be proxied,
- /// e.g. by type, by name, by definition details, etc. They can also return
- /// additional interceptors that should just be applied to the specific object
- /// instance. The default concrete implementation is ObjectNameAutoProxyCreator,
- /// identifying the objects to be proxied via a list of object names.
- /// Any number of TargetSourceCreator implementations can be used with any subclass,
- /// to create a custom target source - for example, to pool prototype objects.
- /// Autoproxying will occur even if there is no advice if a TargetSourceCreator specifies
- /// a custom TargetSource. If there are no TargetSourceCreators set, or if none matches,
- /// a SingletonTargetSource will be used by default to wrap the object to be autoproxied.
- ///
- /// Juergen Hoeller
- /// Rod Johnson
- /// Adhari C Mahendra (.NET)
- ///
- ///
- public abstract class AbstractAutoProxyCreator : ProxyConfig, IInstantiationAwareObjectPostProcessor, IObjectFactoryAware, IOrdered
- {
- #region Protected Fields
-
- ///
- /// The logger for this class hierarchy.
- ///
- protected readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
-
- ///
- /// Convenience constant for subclasses: Return value for "do not proxy".
- ///
- protected static readonly object[] DO_NOT_PROXY = null;
-
- ///
- /// Convenience constant for subclasses: Return value for
- /// "proxy without additional interceptors, just the common ones".
- ///
- protected static readonly object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new object[0];
-
- #endregion
-
- #region Private Fields
-
- ///
- /// Default value is same as non-ordered
- ///
- private int order = int.MaxValue;
-
- ///
- /// Default is global AdvisorAdapterRegistry
- ///
- private IAdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.Instance;
-
-
- ///
- ///
- ///
- private bool freezeProxy = false;
-
- ///
- /// Names of common interceptors.
- /// We must use object name rather than object references
- /// to handle prototype advisors/interceptors.
- /// Default is the empty array: no common interceptors.
- ///
- private string[] interceptorNames = new string[0];
-
- private bool applyCommonInterceptorsFirst = true;
- private IList customTargetSourceCreators = new ArrayList();
- private IObjectFactory owningObjectFactory;
-
- ///
- /// Set of object type + name strings, referring to all objects that this auto-proxy
- /// 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 advisedObjects = new SynchronizedSet(new HashedSet());
-
- private ISet nonAdvisedObjects = new SynchronizedSet(new HashedSet());
-
- #endregion
-
- #region Properties
-
- ///
- /// Sets the AdvisorAdapterRegistry to use.
- ///
- ///
- /// Default is the global AdvisorAdapterRegistry.
- ///
- public IAdvisorAdapterRegistry AdvisorAdapterRegistry
- {
- set { advisorAdapterRegistry = value; }
- }
-
- ///
- /// Sets custom TargetSourceCreators to be applied in this order.
- ///
- ///
- ///
- /// If the list is empty, or they all return null, a SingletonTargetSource
- /// will be created.
- ///
- ///
- /// TargetSourceCreators can only be invoked if this post processor is used
- /// in a IObjectFactory, and its ObjectFactoryAware callback is used.
- ///
- ///
- public IList CustomTargetSourceCreators
- {
- set { customTargetSourceCreators = value; }
- }
-
- ///
- /// Sets the common interceptors, a list of ,
- /// and introduction object names.
- ///
- ///
- ///
- /// If this property isn't set, there will be zero common interceptors.
- /// This is perfectly valid, if "specific" interceptors such as
- /// matching Advisors are all we want.
- ///
- ///
- ///
- /// The list of ,
- /// and introduction object names.
- ///
- ///
- ///
- public string[] InterceptorNames
- {
- set { interceptorNames = value; }
- }
-
- ///
- /// Sets whether the common interceptors should be applied before
- /// object-specific ones.
- ///
- ///
- /// Default is true; else, object-specific interceptors will get applied first.
- ///
- public bool ApplyCommonInterceptorsFirst
- {
- set { applyCommonInterceptorsFirst = value; }
- }
-
- ///
- /// Set whether or not the proxy should be frozen, preventing advice
- /// from being added to it once it is created.
- ///
- ///
- /// Overridden from the super class to prevent the proxy configuration
- /// from being frozen before the proxy is created. The default is not frozen.
- ///
- ///
- public override bool IsFrozen
- {
- get { return freezeProxy; }
- set { this.freezeProxy = value; }
- }
-
- #endregion
-
- #region IObjectPostProcessor Members
-
- ///
- /// 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)
- {
- if (targetSourcedObjects.Contains(objectName))
- {
- return obj;
- }
-
- object cacheKey = GetCacheKey(obj.GetType(), objectName);
- if (nonAdvisedObjects.Contains(cacheKey))
- {
- return obj;
- }
- if (IsInfrastructureType(obj.GetType(), objectName) || ShouldSkip(obj.GetType(), objectName))
- {
- #region Instrumentation
-
- if (logger.IsDebugEnabled)
- {
- logger.Debug(string.Format("Did not attempt to autoproxy infrastructure type [{0}]", obj.GetType().ToString()));
- }
-
- #endregion
-
- 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);
- }
-
-
- // 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));
- }
- nonAdvisedObjects.Add(cacheKey);
- return obj;
- }
-
- ///
- /// No-op for before initialization.
- ///
- /// The obj.
- /// The name.
- ///
- public virtual object PostProcessBeforeInitialization(object obj, string name)
- {
- return obj;
- }
-
- #endregion
-
- #region IObjectFactoryAware Members
-
- ///
- /// Callback that supplies the owning factory to an object instance.
- ///
- ///
- /// Owning
- /// (may not be ). The object can immediately
- /// call methods on the factory.
- ///
- ///
- ///
- /// Invoked after population of normal object properties but before an init
- /// callback like 's
- ///
- /// method or a custom init-method.
- ///
- ///
- ///
- /// In case of initialization errors.
- ///
- public virtual IObjectFactory ObjectFactory
- {
- get { return owningObjectFactory; }
- set { owningObjectFactory = value; }
- }
-
- #endregion
-
- #region IOrdered Members
-
- ///
- /// Propery Order
- ///
- ///
- /// Ordering which will apply to this class's implementation
- /// of Ordered, used when applying multiple ObjectPostProcessors.
- /// Default value is int.MaxValue, meaning that it's non-ordered.
- ///
- public virtual int Order
- {
- get { return order; }
- set { order = value; }
- }
-
- #endregion
-
- #region Protected Methods
-
- ///
- /// Subclasses should override this method to return true if this
- /// object should not be considered for autoproxying by this post processor.
- /// Sometimes we need to be able to avoid this happening if it will lead to
- /// a circular reference. This implementation returns false.
- ///
- /// the type of the object
- /// the name of the object
- /// if remarkable to skip
- protected virtual bool ShouldSkip(Type objectType, string objectName)
- {
- return false;
- }
-
- ///
- /// Subclasses may choose to implement this: for example,
- /// to change the interfaces exposed
- ///
- ///
- /// ProxyFactory that will be used to create the proxy immediably after this method returns.
- ///
- protected virtual void CustomizeProxyFactory(ProxyFactory pf)
- {
- // This implementation does nothing
- }
-
- ///
- /// Determines whether the object is an infrastructure type,
- /// IAdvisor, IAdvice, IAdvisors or AbstractAutoProxyCreator
- ///
- /// The object type to compare
- /// The name of the object
- ///
- /// true if [is infrastructure type] [the specified obj]; otherwise, false.
- ///
- 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);
- }
-
-
- ///
- /// Create a target source for object instances. Uses any
- /// TargetSourceCreators if set. Returns null if no Custom TargetSource
- /// should be used.
- /// This implementation uses the customTargetSourceCreators property.
- /// Subclasses can override this method to use a different mechanism.
- ///
- /// 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)
- {
- // We can't create fancy target sources for directly registered singletons.
- if (customTargetSourceCreators != null &&
- 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);
- 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));
- }
- return ts;
- }
- }
- }
-
- // no custom TargetSource found
- return null;
- }
-
- ///
- /// Return whether the given object is to be proxied, what additional
- /// advices (e.g. AOP Alliance interceptors) and advisors to apply.
- ///
- ///
- /// The previous name of this method was "GetInterceptorAndAdvisorForObject".
- /// It has been renamed in the course of general terminology clarification
- /// in Spring 1.1. An AOP Alliance Interceptor is just a special form of
- /// Advice, so the generic Advice term is preferred now.
- /// The third parameter, customTargetSource, is new in Spring 1.1;
- /// add it to existing implementations of this method.
- ///
- /// the new object instance
- /// the name of the object
- /// targetSource returned by TargetSource property:
- /// may be ignored. Will be null unless a custom target source is in use.
- /// 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);
-
- ///
- /// Create an AOP proxy for the given object.
- ///
- /// Type of the object.
- /// The name of the object.
- /// The set of interceptors that is specific to this
- /// 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)
- {
- ProxyFactory proxyFactory = CreateProxyFactory();
- // copy our properties (proxyTargetClass) inherited from ProxyConfig
- proxyFactory.CopyFrom(this);
-
- object target = targetSource.GetTarget();
-
-
- if(!ProxyTargetType)
- {
- // Must allow for introductions; can't just set interfaces to
- // the target's interfaces only.
- Type[] targetInterfaceTypes = AopUtils.GetAllInterfaces(target);
- foreach (Type interfaceType in targetInterfaceTypes)
- {
- proxyFactory.AddInterface(interfaceType);
- }
- }
-
-
- IAdvisor[] advisors = BuildAdvisors(objectName, specificInterceptors);
-
- foreach (IAdvisor advisor in advisors)
- {
- if (advisor is IIntroductionAdvisor)
- {
- proxyFactory.AddIntroduction((IIntroductionAdvisor)advisor);
- }
- else
- {
- proxyFactory.AddAdvisor(advisor);
- }
- }
- proxyFactory.TargetSource = targetSource;
- CustomizeProxyFactory(proxyFactory);
-
- proxyFactory.IsFrozen = freezeProxy;
- return proxyFactory.GetProxy();
- }
-
- ///
- /// Obtain a new proxy factory instance to be used for proxying a particular object
- ///
- /// A proxy factory instance for proxying a particular object
- protected virtual ProxyFactory CreateProxyFactory()
- {
- return new ProxyFactory();
- }
-
- ///
- /// Determines the advisors for the given object, including the specific interceptors
- /// as well as the common interceptor, all adapted to the Advisor interface.
- ///
- /// The name of the object.
- /// 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)
- {
- // handle prototypes correctly
- IAdvisor[] commonInterceptors = ResolveInterceptorNames();
-
- ArrayList allInterceptors = new ArrayList();
- if (specificInterceptors != null)
- {
- allInterceptors.AddRange(specificInterceptors);
- if (commonInterceptors != null)
- {
- if (applyCommonInterceptorsFirst)
- {
- allInterceptors.InsertRange(0, commonInterceptors);
- }
- else
- {
- allInterceptors.AddRange(commonInterceptors);
- }
- }
- }
- if (logger.IsInfoEnabled)
- {
- 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));
- }
-
-
- IAdvisor[] advisors = new IAdvisor[allInterceptors.Count];
- for (int i = 0; i < allInterceptors.Count; i++)
- {
- advisors[i] = advisorAdapterRegistry.Wrap(allInterceptors[i]);
- }
- return advisors;
- }
-
- ///
- /// Build a cache key for the given object type and object name
- ///
- /// The object type.
- /// The object name.
- /// The cache key for the given type and name
- protected virtual object GetCacheKey(Type objectType, string objectName)
- {
- return objectType.FullName + "_" + objectName;
- }
-
-
- #endregion
-
- #region Private Methods
-
- private IAdvisor[] ResolveInterceptorNames()
- {
- ArrayList advisors = new ArrayList();
- foreach(string name in interceptorNames)
- {
- object next = owningObjectFactory.GetObject(name);
- if (next is IAdvisors)
- {
- advisors.AddRange(((IAdvisors)next).Advisors);
- }
- else
- {
- advisors.Add(advisorAdapterRegistry.Wrap(next));
- }
- }
- return (IAdvisor[])advisors.ToArray(typeof(IAdvisor));
- }
-
- #endregion
-
- #region IInstantiationAwareObjectPostProcessor Members
-
- ///
- /// Create the proxy if have a custom TargetSource
- ///
- /// The object type
- /// The object name
- /// null if not creating a proxy, otherwise return the proxy.
- public object PostProcessBeforeInstantiation(Type objectType, string objectName)
- {
- object cacheKey = GetCacheKey(objectType, objectName);
- if (!targetSourcedObjects.Contains(cacheKey))
- {
- if (advisedObjects.Contains(cacheKey) || nonAdvisedObjects.Contains(cacheKey))
- {
- return null;
- }
- if (IsInfrastructureType(objectType, objectName) || ShouldSkip(objectType, objectName))
- {
- 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);
- if (targetSource != null)
- {
- targetSourcedObjects.Add(objectName);
- object[] specificInterceptors = GetAdvicesAndAdvisorsForObject(objectType, objectName, targetSource);
- return CreateProxy(objectType, objectName, specificInterceptors, targetSource);
- }
- return null;
- }
-
-
- ///
- /// Default behavior, return true and continue processing.
- ///
- /// The object instance
- /// The object name.
- /// true
- public bool PostProcessAfterInstantiation(object objectInstance, string objectName)
- {
- return true;
- }
-
- ///
- /// Default behavior, return passed in PropertyValues
- ///
- /// The property values that the factory is about to apply (never null).
- /// he relevant property infos for the target object (with ignored
- /// dependency types - which the factory handles specifically - already filtered out)
- /// The object instance created, but whose properties have not yet
- /// been set.
- /// Name of the object.
- /// The passed in PropertyValues
- public IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, PropertyInfo[] pis, object objectInstance,
- string objectName)
- {
- return pvs;
- }
-
- #endregion
- }
+ */
+
+#endregion
+
+#region Imports
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Runtime.Remoting;
+using AopAlliance.Aop;
+using Common.Logging;
+using Spring.Aop.Framework.Adapter;
+using Spring.Aop.Target;
+using Spring.Collections;
+using Spring.Core;
+using Spring.Objects;
+using Spring.Objects.Factory;
+using Spring.Objects.Factory.Config;
+using Spring.Util;
+
+#endregion
+
+namespace Spring.Aop.Framework.AutoProxy
+{
+ ///
+ /// ObjectPostProcessor implementation that wraps a group of objects with AOP proxies
+ /// that delegate to the given interceptors before invoking the object itself.
+ ///
+ ///
+ /// This class distinguishes between "common" interceptors: shared for all proxies it
+ /// creates, and "specific" interceptors: unique per object instance. There need not
+ /// be any common interceptors. If there are, they are set using the interceptorNames
+ /// property. As with ProxyFactoryObject, interceptors names in the current factory
+ /// are used rather than object references to allow correct handling of prototype
+ /// advisors and interceptors: for example, to support stateful mixins.
+ /// Any advice type is supported for "interceptorNames" entries.
+ /// Such autoproxying is particularly useful if there's a large number of objects that need
+ /// to be wrapped with similar proxies, i.e. delegating to the same interceptors.
+ /// Instead of x repetitive proxy definitions for x target objects, you can register
+ /// one single such post processor with the object factory to achieve the same effect.
+ /// Subclasses can apply any strategy to decide if a object is to be proxied,
+ /// e.g. by type, by name, by definition details, etc. They can also return
+ /// additional interceptors that should just be applied to the specific object
+ /// instance. The default concrete implementation is ObjectNameAutoProxyCreator,
+ /// identifying the objects to be proxied via a list of object names.
+ /// Any number of TargetSourceCreator implementations can be used with any subclass,
+ /// to create a custom target source - for example, to pool prototype objects.
+ /// Autoproxying will occur even if there is no advice if a TargetSourceCreator specifies
+ /// a custom TargetSource. If there are no TargetSourceCreators set, or if none matches,
+ /// a SingletonTargetSource will be used by default to wrap the object to be autoproxied.
+ ///
+ /// Juergen Hoeller
+ /// Rod Johnson
+ /// Adhari C Mahendra (.NET)
+ ///
+ ///
+ public abstract class AbstractAutoProxyCreator : ProxyConfig, IInstantiationAwareObjectPostProcessor, IObjectFactoryAware, IOrdered
+ {
+ #region Protected Fields
+
+ ///
+ /// The logger for this class hierarchy.
+ ///
+ protected readonly ILog logger = LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );
+
+ ///
+ /// Convenience constant for subclasses: Return value for "do not proxy".
+ ///
+ protected static readonly object[] DO_NOT_PROXY = null;
+
+ ///
+ /// Convenience constant for subclasses: Return value for
+ /// "proxy without additional interceptors, just the common ones".
+ ///
+ protected static readonly object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new object[0];
+
+ #endregion
+
+ #region Private Fields
+
+ ///
+ /// Default value is same as non-ordered
+ ///
+ private int order = int.MaxValue;
+
+ ///
+ /// Default is global AdvisorAdapterRegistry
+ ///
+ private IAdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.Instance;
+
+
+ ///
+ ///
+ ///
+ private bool freezeProxy = false;
+
+ ///
+ /// Names of common interceptors.
+ /// We must use object name rather than object references
+ /// to handle prototype advisors/interceptors.
+ /// Default is the empty array: no common interceptors.
+ ///
+ private string[] interceptorNames = new string[0];
+
+ private bool applyCommonInterceptorsFirst = true;
+ private IList customTargetSourceCreators = new ArrayList();
+ private IObjectFactory owningObjectFactory;
+
+ ///
+ /// Set of object type + name strings, referring to all objects that this auto-proxy
+ /// 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 advisedObjects = new SynchronizedSet( new HashedSet() );
+
+ private ISet nonAdvisedObjects = new SynchronizedSet( new HashedSet() );
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Sets the AdvisorAdapterRegistry to use.
+ ///
+ ///
+ /// Default is the global AdvisorAdapterRegistry.
+ ///
+ public IAdvisorAdapterRegistry AdvisorAdapterRegistry
+ {
+ set { advisorAdapterRegistry = value; }
+ }
+
+ ///
+ /// Sets custom TargetSourceCreators to be applied in this order.
+ ///
+ ///
+ ///
+ /// If the list is empty, or they all return null, a SingletonTargetSource
+ /// will be created.
+ ///
+ ///
+ /// TargetSourceCreators can only be invoked if this post processor is used
+ /// in a IObjectFactory, and its ObjectFactoryAware callback is used.
+ ///
+ ///
+ public IList CustomTargetSourceCreators
+ {
+ set { customTargetSourceCreators = value; }
+ }
+
+ ///
+ /// Sets the common interceptors, a list of ,
+ /// and introduction object names.
+ ///
+ ///
+ ///
+ /// If this property isn't set, there will be zero common interceptors.
+ /// This is perfectly valid, if "specific" interceptors such as
+ /// matching Advisors are all we want.
+ ///
+ ///
+ ///
+ /// The list of ,
+ /// and introduction object names.
+ ///
+ ///
+ ///
+ public string[] InterceptorNames
+ {
+ set { interceptorNames = value; }
+ }
+
+ ///
+ /// Sets whether the common interceptors should be applied before
+ /// object-specific ones.
+ ///
+ ///
+ /// Default is true; else, object-specific interceptors will get applied first.
+ ///
+ public bool ApplyCommonInterceptorsFirst
+ {
+ set { applyCommonInterceptorsFirst = value; }
+ }
+
+ ///
+ /// Set whether or not the proxy should be frozen, preventing advice
+ /// from being added to it once it is created.
+ ///
+ ///
+ /// Overridden from the super class to prevent the proxy configuration
+ /// from being frozen before the proxy is created. The default is not frozen.
+ ///
+ ///
+ public override bool IsFrozen
+ {
+ get { return freezeProxy; }
+ set { this.freezeProxy = value; }
+ }
+
+ #endregion
+
+ #region IObjectPostProcessor Members
+
+ ///
+ /// 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 )
+ {
+ if (targetSourcedObjects.Contains( objectName ))
+ {
+ return obj;
+ }
+
+ object cacheKey = GetCacheKey( obj.GetType(), objectName );
+ if (nonAdvisedObjects.Contains( cacheKey ))
+ {
+ return obj;
+ }
+
+ if (IsInfrastructureType( obj.GetType(), objectName ))
+ {
+ #region Instrumentation
+
+ if (logger.IsDebugEnabled)
+ {
+ logger.Debug( string.Format( "Did not attempt to autoproxy infrastructure type [{0}]", obj.GetType() ) );
+ }
+
+ #endregion
+
+ nonAdvisedObjects.Add( cacheKey );
+ return obj;
+ }
+
+ if (ShouldSkip( obj.GetType(), objectName ))
+ {
+ #region Instrumentation
+
+ if (logger.IsDebugEnabled)
+ {
+ logger.Debug( string.Format( "Skipping type [{0}]", obj.GetType() ) );
+ }
+
+ #endregion
+
+ 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 );
+ }
+
+
+ // 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 ) );
+ }
+ nonAdvisedObjects.Add( cacheKey );
+ return obj;
+ }
+
+ ///
+ /// No-op for before initialization.
+ ///
+ /// The obj.
+ /// The name.
+ ///
+ public virtual object PostProcessBeforeInitialization( object obj, string name )
+ {
+ return obj;
+ }
+
+ #endregion
+
+ #region IObjectFactoryAware Members
+
+ ///
+ /// Callback that supplies the owning factory to an object instance.
+ ///
+ ///
+ /// Owning
+ /// (may not be ). The object can immediately
+ /// call methods on the factory.
+ ///
+ ///
+ ///
+ /// Invoked after population of normal object properties but before an init
+ /// callback like 's
+ ///
+ /// method or a custom init-method.
+ ///
+ ///
+ ///
+ /// In case of initialization errors.
+ ///
+ public virtual IObjectFactory ObjectFactory
+ {
+ get { return owningObjectFactory; }
+ set { owningObjectFactory = value; }
+ }
+
+ #endregion
+
+ #region IOrdered Members
+
+ ///
+ /// Propery Order
+ ///
+ ///
+ /// Ordering which will apply to this class's implementation
+ /// of Ordered, used when applying multiple ObjectPostProcessors.
+ /// Default value is int.MaxValue, meaning that it's non-ordered.
+ ///
+ public virtual int Order
+ {
+ get { return order; }
+ set { order = value; }
+ }
+
+ #endregion
+
+ #region Protected Methods
+
+ ///
+ /// Subclasses should override this method to return true if this
+ /// object should not be considered for autoproxying by this post processor.
+ /// Sometimes we need to be able to avoid this happening if it will lead to
+ /// a circular reference. This implementation returns false.
+ ///
+ /// the type of the object
+ /// the name of the object
+ /// if remarkable to skip
+ protected virtual bool ShouldSkip( Type objectType, string objectName )
+ {
+ return false;
+ }
+
+ ///
+ /// Subclasses may choose to implement this: for example,
+ /// to change the interfaces exposed
+ ///
+ ///
+ /// ProxyFactory that will be used to create the proxy immediably after this method returns.
+ ///
+ protected virtual void CustomizeProxyFactory( ProxyFactory pf )
+ {
+ // This implementation does nothing
+ }
+
+ ///
+ /// Determines whether the object is an infrastructure type,
+ /// IAdvisor, IAdvice, IAdvisors or AbstractAutoProxyCreator
+ ///
+ /// The object type to compare
+ /// The name of the object
+ ///
+ /// true if [is infrastructure type] [the specified obj]; otherwise, false.
+ ///
+ 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 );
+ }
+
+
+ ///
+ /// Create a target source for object instances. Uses any
+ /// TargetSourceCreators if set. Returns null if no Custom TargetSource
+ /// should be used.
+ /// This implementation uses the customTargetSourceCreators property.
+ /// Subclasses can override this method to use a different mechanism.
+ ///
+ /// 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 )
+ {
+ // We can't create fancy target sources for directly registered singletons.
+ if (customTargetSourceCreators != null &&
+ 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 );
+ 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 ) );
+ }
+ return ts;
+ }
+ }
+ }
+
+ // no custom TargetSource found
+ return null;
+ }
+
+ ///
+ /// Return whether the given object is to be proxied, what additional
+ /// advices (e.g. AOP Alliance interceptors) and advisors to apply.
+ ///
+ ///
+ /// The previous name of this method was "GetInterceptorAndAdvisorForObject".
+ /// It has been renamed in the course of general terminology clarification
+ /// in Spring 1.1. An AOP Alliance Interceptor is just a special form of
+ /// Advice, so the generic Advice term is preferred now.
+ /// The third parameter, customTargetSource, is new in Spring 1.1;
+ /// add it to existing implementations of this method.
+ ///
+ /// the new object instance
+ /// the name of the object
+ /// targetSource returned by TargetSource property:
+ /// may be ignored. Will be null unless a custom target source is in use.
+ /// 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 );
+
+ ///
+ /// Create an AOP proxy for the given object.
+ ///
+ /// Type of the object.
+ /// The name of the object.
+ /// The set of interceptors that is specific to this
+ /// 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 )
+ {
+ ProxyFactory proxyFactory = CreateProxyFactory();
+ // copy our properties (proxyTargetClass) inherited from ProxyConfig
+ proxyFactory.CopyFrom( this );
+
+ object target = targetSource.GetTarget();
+
+
+ if (!ProxyTargetType)
+ {
+ // Must allow for introductions; can't just set interfaces to
+ // the target's interfaces only.
+ Type[] targetInterfaceTypes = AopUtils.GetAllInterfaces( target );
+ foreach (Type interfaceType in targetInterfaceTypes)
+ {
+ proxyFactory.AddInterface( interfaceType );
+ }
+ }
+
+
+ IAdvisor[] advisors = BuildAdvisors( objectName, specificInterceptors );
+
+ foreach (IAdvisor advisor in advisors)
+ {
+ if (advisor is IIntroductionAdvisor)
+ {
+ proxyFactory.AddIntroduction( (IIntroductionAdvisor)advisor );
+ }
+ else
+ {
+ proxyFactory.AddAdvisor( advisor );
+ }
+ }
+ proxyFactory.TargetSource = targetSource;
+ CustomizeProxyFactory( proxyFactory );
+
+ proxyFactory.IsFrozen = freezeProxy;
+ return proxyFactory.GetProxy();
+ }
+
+ ///
+ /// Obtain a new proxy factory instance to be used for proxying a particular object
+ ///
+ /// A proxy factory instance for proxying a particular object
+ protected virtual ProxyFactory CreateProxyFactory()
+ {
+ return new ProxyFactory();
+ }
+
+ ///
+ /// Determines the advisors for the given object, including the specific interceptors
+ /// as well as the common interceptor, all adapted to the Advisor interface.
+ ///
+ /// The name of the object.
+ /// 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 )
+ {
+ // handle prototypes correctly
+ IAdvisor[] commonInterceptors = ResolveInterceptorNames();
+
+ ArrayList allInterceptors = new ArrayList();
+ if (specificInterceptors != null)
+ {
+ allInterceptors.AddRange( specificInterceptors );
+ if (commonInterceptors != null)
+ {
+ if (applyCommonInterceptorsFirst)
+ {
+ allInterceptors.InsertRange( 0, commonInterceptors );
+ }
+ else
+ {
+ allInterceptors.AddRange( commonInterceptors );
+ }
+ }
+ }
+ if (logger.IsInfoEnabled)
+ {
+ 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 ) );
+ }
+
+
+ IAdvisor[] advisors = new IAdvisor[allInterceptors.Count];
+ for (int i = 0; i < allInterceptors.Count; i++)
+ {
+ advisors[i] = advisorAdapterRegistry.Wrap( allInterceptors[i] );
+ }
+ return advisors;
+ }
+
+ ///
+ /// Build a cache key for the given object type and object name
+ ///
+ /// The object type.
+ /// The object name.
+ /// The cache key for the given type and name
+ protected virtual object GetCacheKey( Type objectType, string objectName )
+ {
+ return objectType.FullName + "_" + objectName;
+ }
+
+
+ #endregion
+
+ #region Private Methods
+
+ private IAdvisor[] ResolveInterceptorNames()
+ {
+ ArrayList advisors = new ArrayList();
+ foreach (string name in interceptorNames)
+ {
+ object next = owningObjectFactory.GetObject( name );
+ if (next is IAdvisors)
+ {
+ advisors.AddRange( ((IAdvisors)next).Advisors );
+ }
+ else
+ {
+ advisors.Add( advisorAdapterRegistry.Wrap( next ) );
+ }
+ }
+ return (IAdvisor[])advisors.ToArray( typeof( IAdvisor ) );
+ }
+
+ #endregion
+
+ #region IInstantiationAwareObjectPostProcessor Members
+
+ ///
+ /// Create the proxy if have a custom TargetSource
+ ///
+ /// The object type
+ /// The object name
+ /// null if not creating a proxy, otherwise return the proxy.
+ public object PostProcessBeforeInstantiation( Type objectType, string objectName )
+ {
+ object cacheKey = GetCacheKey( objectType, objectName );
+ if (!targetSourcedObjects.Contains( cacheKey ))
+ {
+ if (advisedObjects.Contains( cacheKey ) || nonAdvisedObjects.Contains( cacheKey ))
+ {
+ return null;
+ }
+
+ if (IsInfrastructureType( objectType, objectName ))
+ {
+ #region Instrumentation
+
+ if (logger.IsDebugEnabled)
+ {
+ logger.Debug( string.Format( "Did not attempt to autoproxy infrastructure type [{0}]", objectType ) );
+ }
+
+ #endregion
+
+ nonAdvisedObjects.Add( cacheKey );
+ return null;
+ }
+
+ if (ShouldSkip( objectType, objectName ))
+ {
+ #region Instrumentation
+
+ if (logger.IsDebugEnabled)
+ {
+ logger.Debug( string.Format( "Skipping type [{0}]", objectType ) );
+ }
+
+ #endregion
+
+ 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 );
+ if (targetSource != null)
+ {
+ targetSourcedObjects.Add( objectName );
+ object[] specificInterceptors = GetAdvicesAndAdvisorsForObject( objectType, objectName, targetSource );
+ return CreateProxy( objectType, objectName, specificInterceptors, targetSource );
+ }
+ return null;
+ }
+
+
+ ///
+ /// Default behavior, return true and continue processing.
+ ///
+ /// The object instance
+ /// The object name.
+ /// true
+ public bool PostProcessAfterInstantiation( object objectInstance, string objectName )
+ {
+ return true;
+ }
+
+ ///
+ /// Default behavior, return passed in PropertyValues
+ ///
+ /// The property values that the factory is about to apply (never null).
+ /// he relevant property infos for the target object (with ignored
+ /// dependency types - which the factory handles specifically - already filtered out)
+ /// The object instance created, but whose properties have not yet
+ /// been set.
+ /// Name of the object.
+ /// The passed in PropertyValues
+ public IPropertyValues PostProcessPropertyValues( IPropertyValues pvs, PropertyInfo[] pis, object objectInstance,
+ string objectName )
+ {
+ return pvs;
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractFilteringAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractFilteringAutoProxyCreator.cs
new file mode 100644
index 00000000..5462b463
--- /dev/null
+++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractFilteringAutoProxyCreator.cs
@@ -0,0 +1,81 @@
+#region License
+
+/*
+ * Copyright © 2002-2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.Collections;
+using Spring.Objects.Factory;
+using Spring.Util;
+
+#endregion
+
+namespace Spring.Aop.Framework.AutoProxy
+{
+ ///
+ /// The base class for AutoProxyCreator implementations that mark objects
+ /// eligible for proxying based on arbitrary criteria.
+ ///
+ /// Erich Eichinger
+ public abstract class AbstractFilteringAutoProxyCreator : AbstractAutoProxyCreator
+ {
+ ///
+ ///Overridden to call .
+ ///
+ /// the type of the object
+ /// the name of the object
+ /// if remarkable to skip
+ protected override bool ShouldSkip( Type objectType, string objectName )
+ {
+ bool shouldSkip = !IsEligibleForProxying( objectType, objectName );
+ return shouldSkip;
+ }
+
+ ///
+ /// Override to always return .
+ ///
+ ///
+ /// Whether an object shall be proxied or not is determined by the result of .
+ ///
+ /// ingored
+ /// ignored
+ /// ignored
+ ///
+ /// Always to indicate, that the object shall be proxied.
+ ///
+ ///
+ protected override object[] GetAdvicesAndAdvisorsForObject( Type objType, string name, ITargetSource customTargetSource )
+ {
+ return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
+ }
+
+ ///
+ /// Decide, whether the given object is eligible for proxying.
+ ///
+ ///
+ /// Override this method to allow or reject proxying for the given object.
+ ///
+ /// the object's type
+ /// the name of the object
+ ///
+ /// whether the given object shall be proxied.
+ protected abstract bool IsEligibleForProxying( Type objType, string name );
+ }
+}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AttributeAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AttributeAutoProxyCreator.cs
new file mode 100644
index 00000000..66d6de06
--- /dev/null
+++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AttributeAutoProxyCreator.cs
@@ -0,0 +1,115 @@
+#region License
+
+/*
+ * Copyright © 2002-2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.Collections;
+using Spring.Aop.Support;
+using Spring.Util;
+
+#endregion
+
+namespace Spring.Aop.Framework.AutoProxy
+{
+ ///
+ /// An AutoProxyCreator, that identifies objects to be proxied by checking s defined on their type.
+ ///
+ /// Erich Eichinger
+ public class AttributeAutoProxyCreator : AbstractFilteringAutoProxyCreator
+ {
+ private bool _checkInherited = false;
+ private Type[] _attributeTypes = null;
+
+ ///
+ /// Indicates, whether to consider base types for filtering when checking declared attributes. Defaults to false.
+ ///
+ public bool CheckInherited
+ {
+ get { return _checkInherited; }
+ set { _checkInherited = value; }
+ }
+
+ ///
+ /// The list of attribute types marking object types as eligible for auto-proxying by this AutoProxyCreator. Must not be null.
+ ///
+ public Type[] AttributeTypes
+ {
+ get { return _attributeTypes; }
+ set
+ {
+ AssertUtils.ArgumentNotNull( value, "AttributeTypes" );
+ _attributeTypes = value;
+ }
+ }
+
+ ///
+ /// Determines, whether the given object shall be proxied by matching against .
+ ///
+ /// the object's type
+ /// the name of the object
+ protected override bool IsEligibleForProxying( Type objType, string name )
+ {
+ AssertUtils.ArgumentNotNull(this.AttributeTypes, "AttributeTypes");
+
+ bool shallProxy = IsAnnotatedWithAnyOfAttribute( objType, this.AttributeTypes, this.CheckInherited );
+ return shallProxy;
+ }
+
+ ///
+ /// Checks if is annotated with any of the attributes within the given list of .
+ ///
+ /// the object's type
+ /// the list of types to match agains.
+ /// whether to check base classes and intefaces for any of the given attributes.
+ /// if any of the attributes is found
+ protected virtual bool IsAnnotatedWithAnyOfAttribute( Type objectType, Type[] attributeTypes, bool checkInherited )
+ {
+ foreach(Type attributeType in attributeTypes)
+ {
+ if (IsAnnotatedWithAttribute(objectType, attributeType, checkInherited))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Checks if is annotated with the specified .
+ ///
+ /// the object's type
+ /// the type to match agains.
+ /// whether to check base classes and intefaces for the specified attribute.
+ /// if the attributes is found
+ protected virtual bool IsAnnotatedWithAttribute( Type objectType, Type attributeType, bool checkInherited )
+ {
+ if (checkInherited)
+ {
+ return AttributeUtils.FindAttribute( objectType, attributeType ) != null;
+ }
+ else
+ {
+ object[] atts = objectType.GetCustomAttributes( attributeType, false );
+ return ArrayUtils.HasLength( atts );
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectNameAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectNameAutoProxyCreator.cs
index 5d63b4b9..137ad39a 100644
--- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectNameAutoProxyCreator.cs
+++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectNameAutoProxyCreator.cs
@@ -30,7 +30,7 @@ using Spring.Util;
namespace Spring.Aop.Framework.AutoProxy
{
///
- /// Object Auto Proxy Creator
+ /// AutoProxyCreator that identifies objects to proxy via a list of names.
///
///
///
@@ -46,10 +46,16 @@ namespace Spring.Aop.Framework.AutoProxy
///
/// Juergen Hoeller
/// Adhari C Mahendra (.NET)
- public class ObjectNameAutoProxyCreator : AbstractAutoProxyCreator
+ public class ObjectNameAutoProxyCreator : AbstractFilteringAutoProxyCreator
{
private IList objectNames;
+ ///
+ /// Initializes a new instance of .
+ ///
+ public ObjectNameAutoProxyCreator()
+ {}
+
///
/// Set the names of the objects in IList fashioned way that should automatically
/// get wrapped with proxies.
@@ -62,47 +68,15 @@ namespace Spring.Aop.Framework.AutoProxy
get { return objectNames; }
}
- ///
- /// Determines, whether the given object shall be proxied.
- ///
- ///
- /// if the object shall be proxied.
- /// otherwise.
- ///
- protected override object[] GetAdvicesAndAdvisorsForObject( Type objType, string name, ITargetSource customTargetSource )
- {
- if (ShallProxy( objType, name, customTargetSource ))
- {
- return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
- }
- return DO_NOT_PROXY;
- }
-
///
/// Identify as object to proxy if the object name is in the configured list of names.
///
- protected virtual bool ShallProxy( Type objType, string name, ITargetSource customTargetSource )
+ protected override bool IsEligibleForProxying( Type objType, string name )
{
- if (objectNames != null)
- {
- for (int i = 0; i < objectNames.Count; i++)
- {
- string mappedName = String.Copy( (string)objectNames[i] );
- if (typeof( IFactoryObject ).IsAssignableFrom( objType ))
- {
- if (!name.StartsWith( ObjectFactoryUtils.FactoryObjectPrefix ))
- {
- continue;
- }
- mappedName = mappedName.Substring( ObjectFactoryUtils.FactoryObjectPrefix.Length );
- }
- if (IsMatch( name, mappedName ))
- {
- return true;
- }
- }
- }
- return false;
+ AssertUtils.ArgumentNotNull(this.ObjectNames, "ObjectNames");
+
+ bool shallProxy = PatternMatchUtils.IsObjectNameMatch(objType, name, this.ObjectNames, new PatternMatchUtils.ObjectNameMatchPredicate(IsMatch), ObjectFactoryUtils.FactoryObjectPrefix);
+ return shallProxy;
}
///
diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreator.cs
index 18b09d7a..38df5772 100644
--- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreator.cs
+++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreator.cs
@@ -34,7 +34,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// be further restricted by specifying object name patterns like with .
///
/// Erich Eichinger
- public class PointcutFilteringAutoProxyCreator : ObjectNameAutoProxyCreator
+ public class PointcutFilteringAutoProxyCreator : AbstractFilteringAutoProxyCreator
{
private IPointcut _pointcut;
@@ -44,34 +44,18 @@ namespace Spring.Aop.Framework.AutoProxy
public IPointcut Pointcut
{
set { _pointcut = value; }
+ get { return _pointcut; }
}
///
/// Determines, whether the given object shall be proxied.
///
- protected override bool ShallProxy( Type objType, string name, ITargetSource customTargetSource )
+ protected override bool IsEligibleForProxying( Type objType, string name )
{
- if (CollectionUtils.IsEmpty( ObjectNames ) && _pointcut == null)
- {
- throw new ArgumentException("At least one of ObjectNames and Pointcut criteria are required");
- }
+ AssertUtils.ArgumentNotNull(_pointcut, "Pointcut");
- bool isObjectNameMatch = base.ShallProxy( objType, name, customTargetSource );
-
- // we have a name match, but empty pointcut -> ok
- if (isObjectNameMatch && _pointcut==null)
- {
- return true;
- }
-
- // positive name match or no names specified -> get the pointcut match
- if ( (isObjectNameMatch || CollectionUtils.IsEmpty(ObjectNames) )
- && _pointcut != null)
- {
- return AopUtils.CanApply( _pointcut, objType, null );
- }
-
- return false;
+ bool shallProxy = AopUtils.CanApply( _pointcut, objType, null );
+ return shallProxy;
}
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/TypeNameAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/TypeNameAutoProxyCreator.cs
new file mode 100644
index 00000000..777c03a4
--- /dev/null
+++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/TypeNameAutoProxyCreator.cs
@@ -0,0 +1,70 @@
+#region License
+
+/*
+ * Copyright © 2002-2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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 Spring.Aop.Support;
+using Spring.Util;
+
+#endregion
+
+namespace Spring.Aop.Framework.AutoProxy
+{
+ ///
+ /// AutoProxyCreator, that identifies objects to proxy by matching their against a list of patterns.
+ ///
+ /// Erich Eichinger
+ public class TypeNameAutoProxyCreator : AbstractFilteringAutoProxyCreator
+ {
+ private TypeNameTypeFilter _typeNameFilter = null;
+
+ ///
+ /// The list of patterns to match against. For pattern syntax, see
+ ///
+ public string[] TypeNames
+ {
+ get { return _typeNameFilter.TypeNamePatterns; }
+ set
+ {
+ AssertUtils.ArgumentNotNull(value, "TypeNames");
+ _typeNameFilter = new TypeNameTypeFilter(value);
+ }
+ }
+
+ ///
+ /// Decide, whether the given object is eligible for proxying.
+ ///
+ ///
+ /// Override this method to allow or reject proxying for the given object.
+ ///
+ /// the object's type
+ /// the name of the object
+ ///
+ /// whether the given object shall be proxied.
+ protected override bool IsEligibleForProxying(Type objType, string name)
+ {
+ AssertUtils.ArgumentNotNull(_typeNameFilter, "TypeNames");
+
+ bool shallProxy = _typeNameFilter.Matches(objType);
+ return shallProxy;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Aop/Support/AttributeTypeFilter.cs b/src/Spring/Spring.Aop/Aop/Support/AttributeTypeFilter.cs
index 84fbeb14..3633df19 100644
--- a/src/Spring/Spring.Aop/Aop/Support/AttributeTypeFilter.cs
+++ b/src/Spring/Spring.Aop/Aop/Support/AttributeTypeFilter.cs
@@ -31,9 +31,24 @@ namespace Spring.Aop.Support
public class AttributeTypeFilter : ITypeFilter
{
private readonly Type attributeType;
-
private readonly bool checkInherited;
+ ///
+ /// The attribute for this filter.
+ ///
+ public Type AttributeType
+ {
+ get { return attributeType; }
+ }
+
+ ///
+ /// Indicates, whether this filter considers base types for filtering.
+ ///
+ public bool CheckInherited
+ {
+ get { return checkInherited; }
+ }
+
///
/// Initializes a new instance of the class for the
/// given attribute type.
@@ -80,9 +95,11 @@ namespace Spring.Aop.Support
if (checkInherited)
{
return AttributeUtils.FindAttribute(type, attributeType) != null;
- } else
+ }
+ else
{
- return Attribute.GetCustomAttributes(type, attributeType, false) != null;
+ object[] atts = type.GetCustomAttributes(attributeType, false);
+ return ArrayUtils.HasLength(atts);
}
}
diff --git a/src/Spring/Spring.Aop/Aop/Support/TypeNameTypeFilter.cs b/src/Spring/Spring.Aop/Aop/Support/TypeNameTypeFilter.cs
new file mode 100644
index 00000000..49688927
--- /dev/null
+++ b/src/Spring/Spring.Aop/Aop/Support/TypeNameTypeFilter.cs
@@ -0,0 +1,75 @@
+#region License
+
+/*
+ * Copyright © 2002-2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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 Spring.Util;
+
+#endregion
+
+namespace Spring.Aop.Support
+{
+ ///
+ /// Simple implementation that matches
+ /// a given 's against .
+ /// For a list of supported pattern syntax see .
+ ///
+ /// Erich Eichinger
+ ///
+ public class TypeNameTypeFilter : ITypeFilter
+ {
+ private string[] _typeNamePatterns;
+
+ ///
+ /// Returns the list of type name patterns for this filter.
+ ///
+ ///
+ public string[] TypeNamePatterns
+ {
+ get { return _typeNamePatterns; }
+ }
+
+ ///
+ ///Creates a new instance of using a list of given .
+ ///
+ ///the list patterns to match typenames against. Must not be null.
+ ///
+ public TypeNameTypeFilter(string[] patterns)
+ {
+ AssertUtils.ArgumentNotNull(patterns, "patterns");
+ _typeNamePatterns = patterns;
+ }
+
+ ///
+ /// Does the supplied type's match any of the ?
+ ///
+ ///
+ /// The candidate .
+ ///
+ ///
+ /// if the matches any of the .
+ ///
+ public bool Matches(Type type)
+ {
+ return PatternMatchUtils.SimpleMatch(_typeNamePatterns, type.FullName);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Spring.Aop.2008.csproj b/src/Spring/Spring.Aop/Spring.Aop.2008.csproj
index 57c87c8c..13bd5343 100644
--- a/src/Spring/Spring.Aop/Spring.Aop.2008.csproj
+++ b/src/Spring/Spring.Aop/Spring.Aop.2008.csproj
@@ -136,8 +136,11 @@
+
+
+
@@ -359,6 +362,7 @@
Code
+
Code
diff --git a/src/Spring/Spring.Core/Util/PatternMatchUtils.cs b/src/Spring/Spring.Core/Util/PatternMatchUtils.cs
index c577ce0e..8feae635 100644
--- a/src/Spring/Spring.Core/Util/PatternMatchUtils.cs
+++ b/src/Spring/Spring.Core/Util/PatternMatchUtils.cs
@@ -21,8 +21,10 @@
#region Imports
using System;
+using System.Collections;
using System.Reflection;
-using System.Text.RegularExpressions;
+using System.Text.RegularExpressions;
+using Spring.Objects.Factory;
#endregion
@@ -94,5 +96,56 @@ namespace Spring.Util
}
return false;
}
+
+ ///
+ /// Signature of callbacks that may be used for matching object names.
+ ///
+ /// the object name to check.
+ /// the pattern to match against.
+ /// true, if the matches
+ ///
+ public delegate bool ObjectNameMatchPredicate(string objectName, string namePattern);
+
+ ///
+ /// Convenience method that may be used by derived classes. Iterates over the list of to match against.
+ ///
+ /// the object's type. Must not be null.
+ /// the name of the object Must not be null.
+ /// the list of patterns, that shall be matched against. Must not be null.
+ ///
+ /// the used for
+ /// matching against each pattern in . Must not be null.
+ ///
+ /// the prefix to be used for dereferencing factory object names.
+ ///
+ /// If is null, will always return true, otherwise
+ /// if matches any of the patterns specified in .
+ ///
+ public static bool IsObjectNameMatch(Type objType, string objectName, IList objectNamePatterns, ObjectNameMatchPredicate isMatchPredicate, string factoryObjectPrefix)
+ {
+ AssertUtils.ArgumentNotNull(objType, "objType");
+ AssertUtils.ArgumentNotNull(objectName, "objectName");
+ AssertUtils.ArgumentNotNull(objectNamePatterns, "objectNamePatterns");
+ AssertUtils.ArgumentNotNull(isMatchPredicate, "isMatchPredicate");
+ AssertUtils.ArgumentNotNull(factoryObjectPrefix, "factoryObjectPrefix");
+
+ for (int i = 0; i < objectNamePatterns.Count; i++)
+ {
+ string mappedName = (string)objectNamePatterns[i];
+ if (typeof( IFactoryObject ).IsAssignableFrom( objType ))
+ {
+ if (!objectName.StartsWith( factoryObjectPrefix ))
+ {
+ continue;
+ }
+ mappedName = mappedName.Substring( factoryObjectPrefix.Length );
+ }
+ if (isMatchPredicate( objectName, mappedName ))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
}
}
\ No newline at end of file
diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AttributeAutoProxyCreatorTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AttributeAutoProxyCreatorTests.cs
new file mode 100644
index 00000000..4ea9f5ba
--- /dev/null
+++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AttributeAutoProxyCreatorTests.cs
@@ -0,0 +1,150 @@
+#region License
+
+/*
+ * Copyright © 2002-2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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 NUnit.Framework;
+using Spring.Objects;
+using Spring.Stereotype;
+
+#endregion
+
+namespace Spring.Aop.Framework.AutoProxy
+{
+ ///
+ ///
+ ///
+ /// Erich Eichinger
+ [TestFixture]
+ public class AttributeAutoProxyCreatorTests
+ {
+ public interface IEmptyInterface
+ {}
+
+ [AttributeUsage( AttributeTargets.Class|AttributeTargets.Method, Inherited=false )]
+ private class ApcTestAttribute : Attribute {}
+
+ private class ApcTestObject: IEmptyInterface {}
+
+ [ApcTest]
+ private class AttributedApcTestObject : ApcTestObject
+ {}
+
+ private class DerivedAttributedApcTestObject : AttributedApcTestObject
+ {
+ [ApcTest]
+ public void SomeMethod() {}
+ }
+
+ [Test]
+ [ExpectedException( typeof( ArgumentNullException ) )]
+ public void ThrowsOnMissingAttributeTypeList()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.PostProcessAfterInitialization( new ApcTestObject(), "testObject" );
+ }
+
+ [Test]
+ [ExpectedException( typeof( ArgumentNullException ) )]
+ public void ThrowsOnAssigningNullAttributeList()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.AttributeTypes = null;
+ }
+
+ [Test]
+ public void AllowsEmptyAttributeList()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.AttributeTypes = new Type[0];
+ apc.PostProcessAfterInitialization( new ApcTestObject(), "testObject" );
+ }
+
+ [Test]
+ public void DefaultsToNotCheckInherited()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ Assert.IsFalse(apc.CheckInherited);
+ }
+
+ [Test]
+ public void CreatesProxyOnAttributeMatch()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.AttributeTypes = new Type[] { typeof(ApcTestAttribute) };
+
+ object result = apc.PostProcessAfterInitialization( new AttributedApcTestObject(), "testObject" );
+ Assert.IsTrue( AopUtils.IsAopProxy( result ) );
+ }
+
+ [Test]
+ public void CreatesProxyOnInheritedAttributeMatchWhenCheckInherited()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.AttributeTypes = new Type[] { typeof(ApcTestAttribute) };
+ apc.CheckInherited = true;
+ object result = apc.PostProcessAfterInitialization( new DerivedAttributedApcTestObject(), "testObject" );
+ Assert.IsTrue( AopUtils.IsAopProxy( result ) );
+ }
+
+ [Test]
+ public void DoesNotCreateProxyOnInheritedAttributeMatchWhenNotCheckInherited()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.AttributeTypes = new Type[] { typeof(ApcTestAttribute) };
+ apc.CheckInherited = false;
+ object result = apc.PostProcessAfterInitialization( new DerivedAttributedApcTestObject(), "testObject" );
+ Assert.IsFalse( AopUtils.IsAopProxy( result ) );
+ }
+
+ [Test]
+ public void DoesNotCreateProxyIfNoAttributeMatch()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.AttributeTypes = new Type[] { typeof(ApcTestAttribute) };
+
+ object result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
+ Assert.IsFalse( AopUtils.IsAopProxy( result ) );
+ }
+
+ [Test]
+ public void DoesNotCheckMethodLevelAttributes()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.AttributeTypes = new Type[] { typeof(ApcTestAttribute) };
+ apc.CheckInherited = false; // (!)
+
+ // does not check method level attributes!
+ object result = apc.PostProcessAfterInitialization( new DerivedAttributedApcTestObject(), "testObject" );
+ Assert.IsFalse( AopUtils.IsAopProxy( result ) );
+ }
+
+ [Test]
+ public void DoesNotCreateProxyIfEmptyAtributeList()
+ {
+ AttributeAutoProxyCreator apc = new AttributeAutoProxyCreator();
+ apc.AttributeTypes = new Type[0];
+
+ object result = apc.PostProcessAfterInitialization( new ApcTestObject(), "testObject" );
+ Assert.IsFalse( AopUtils.IsAopProxy( result ) );
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreatorTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreatorTests.cs
index 549d3ec8..3554c421 100644
--- a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreatorTests.cs
+++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreatorTests.cs
@@ -36,58 +36,30 @@ namespace Spring.Aop.Framework.AutoProxy
[TestFixture]
public class PointcutFilteringAutoProxyCreatorTests
{
- [Test]
- public void CreatesProxyOnlyIfPointcutAndObjectNameMatch()
- {
- // is match
- PointcutFilteringAutoProxyCreator apc = new PointcutFilteringAutoProxyCreator();
- apc.ObjectNames = new string[] { "test*" } ;;
- apc.Pointcut = new SdkRegularExpressionMethodPointcut(".*\\.GetHashCode");
- object result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
- Assert.IsTrue(AopUtils.IsAopProxy(result));
-
- apc = new PointcutFilteringAutoProxyCreator();
- apc.ObjectNames = new string[] { "test*" } ;;
- apc.Pointcut = new SdkRegularExpressionMethodPointcut(".*\\.GetHashCODE");
- result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
- Assert.IsFalse(AopUtils.IsAopProxy(result));
-
- apc = new PointcutFilteringAutoProxyCreator();
- apc.ObjectNames = new string[] { "tesT*" } ;;
- apc.Pointcut = new SdkRegularExpressionMethodPointcut(".*\\.GetHashCode");
- result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
- Assert.IsFalse(AopUtils.IsAopProxy(result));
- }
-
[Test]
public void CreatesProxyOnPointcutMatch()
{
PointcutFilteringAutoProxyCreator apc = new PointcutFilteringAutoProxyCreator();
- apc.ObjectNames = null;
apc.Pointcut = new SdkRegularExpressionMethodPointcut(".*\\.GetHashCode");
object result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
Assert.IsTrue(AopUtils.IsAopProxy(result));
}
[Test]
- public void CreatesProxyOnNameMatch()
+ public void DoesNotCreateProxyIfNoPointcutMatch()
{
PointcutFilteringAutoProxyCreator apc = new PointcutFilteringAutoProxyCreator();
- apc.ObjectNames = new string[] { "test*" } ;
- apc.Pointcut = null;
+ apc.Pointcut = new SdkRegularExpressionMethodPointcut(".*\\.DOEsNOTExist");
object result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
- Assert.IsTrue(AopUtils.IsAopProxy(result));
+ Assert.IsFalse(AopUtils.IsAopProxy(result));
}
[Test]
- [ExpectedException(typeof(ArgumentException))]
+ [ExpectedException(typeof(ArgumentNullException))]
public void ThrowsArgumentExceptionIfNoCriteriaSpecified()
{
PointcutFilteringAutoProxyCreator apc = new PointcutFilteringAutoProxyCreator();
- apc.ObjectNames = new string[] {} ;
- apc.Pointcut = null;
- object result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
- Assert.IsTrue(AopUtils.IsAopProxy(result));
+ apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
}
}
}
\ No newline at end of file
diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/TypeNameAutoProxyCreatorTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/TypeNameAutoProxyCreatorTests.cs
new file mode 100644
index 00000000..818bdd9f
--- /dev/null
+++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/TypeNameAutoProxyCreatorTests.cs
@@ -0,0 +1,98 @@
+#region License
+
+/*
+ * Copyright © 2002-2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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 NUnit.Framework;
+using Spring.Objects;
+
+#endregion
+
+namespace Spring.Aop.Framework.AutoProxy
+{
+ ///
+ ///
+ ///
+ /// Erich Eichinger
+ [TestFixture]
+ public class TypeNameAutoProxyCreatorTests
+ {
+ private class MyLocalTestObject: TestObject
+ {}
+
+ [Test]
+ [ExpectedException( typeof( ArgumentNullException ) )]
+ public void ThrowsOnMissingTypeNames()
+ {
+ TypeNameAutoProxyCreator apc = new TypeNameAutoProxyCreator();
+ apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
+ }
+
+ [Test]
+ [ExpectedException( typeof( ArgumentNullException ) )]
+ public void ThrowsOnAssigningNullTypeNames()
+ {
+ TypeNameAutoProxyCreator apc = new TypeNameAutoProxyCreator();
+ apc.TypeNames = null;
+ }
+
+ [Test]
+ public void AllowsEmptyTypeNameList()
+ {
+ TypeNameAutoProxyCreator apc = new TypeNameAutoProxyCreator();
+ apc.TypeNames = new string[] {};
+
+ apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
+ }
+
+ [Test]
+ public void CreatesProxyOnTypeNameMatch()
+ {
+ TypeNameAutoProxyCreator apc = new TypeNameAutoProxyCreator();
+ apc.TypeNames = new string[] { "Spring.Objects.Test*", "*MyLocal*" };
+
+ object result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
+ Assert.IsTrue( AopUtils.IsAopProxy( result ) );
+ result = apc.PostProcessAfterInitialization( new MyLocalTestObject(), "myLocalTestObject" );
+ Assert.IsTrue( AopUtils.IsAopProxy( result ) );
+ }
+
+ [Test]
+ public void DoesNotCreateProxyIfNoTypeNameMatch()
+ {
+ TypeNameAutoProxyCreator apc = new TypeNameAutoProxyCreator();
+ apc.TypeNames = new string[] { "Foo*" };
+
+ object result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
+ Assert.IsFalse( AopUtils.IsAopProxy( result ) );
+ }
+
+ [Test]
+ public void DoesNotCreateProxyIfEmptyTypeNameList()
+ {
+ TypeNameAutoProxyCreator apc = new TypeNameAutoProxyCreator();
+ apc.TypeNames = new string[] {};
+
+ object result = apc.PostProcessAfterInitialization( new TestObject(), "testObject" );
+ Assert.IsFalse( AopUtils.IsAopProxy( result ) );
+ }
+ }
+}
\ No newline at end of file
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 10e9d433..153b74f4 100644
--- a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj
+++ b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj
@@ -125,6 +125,7 @@
+
@@ -132,6 +133,7 @@
+