fixed SPRNET-1225

fixed SPRNET-1224
This commit is contained in:
eeichinger
2009-06-27 03:09:55 +00:00
parent c6c8d03dc7
commit 60ecf0e05d
29 changed files with 943 additions and 661 deletions

View File

@@ -30,12 +30,19 @@ Spring.Core
A new property MsgDelivery has been added. The class, CachedMessageProducer, which is unlikely to be use by
end users, was directly upgraded to the latest API without any backwards compatibility support.
4. AbstractApplicationContext.CaseSensitive renamed to AbstractApplicationContext.IsCaseSensitive
Spring.Aop
----------
1. AbstractAutoProxyCreator.FindEligibleAdvisors(Type) changed to
AbstractAutoProxyCreator.FindEligibleAdvisors(Type, Name)
2. It is not possible to change a ProxyFactoryObject's product configuration at runtime
if IsSingleton==true since factory object singleton products get cached now.
Changes (1.2 RC1 to 1.2.0 or greater)
=====================================

View File

@@ -42,7 +42,7 @@ namespace Spring.Aop.Framework.Adapter
/// <author>Aleksandar Seovic (.NET)</author>
public class DefaultAdvisorAdapterRegistry : IAdvisorAdapterRegistry
{
private IList adapters = new ArrayList();
private readonly IList adapters = new ArrayList();
/// <summary>
/// Creates a new instance of the

View File

@@ -21,6 +21,8 @@
#region Imports
using System;
using System.Collections;
using Spring.Context;
using Spring.Objects.Factory;
#endregion
@@ -35,7 +37,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Erich Eichinger (.NET)</author>
public class DefaultAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator, IObjectNameAware
public class DefaultAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator, IObjectNameAware, IInitializingObject
{
/// <summary>
/// Separator between prefix and remainder of object name
@@ -43,6 +45,7 @@ namespace Spring.Aop.Framework.AutoProxy
public static readonly string SEPARATOR = ".";
private bool usePrefix;
private string advisorObjectNamePrefix;
private IList cachedAdvisors;
#region Properties
@@ -97,7 +100,21 @@ namespace Spring.Aop.Framework.AutoProxy
}
}
#endregion
#endregion
/// <summary>
/// Find all possible advisor candidates to use in auto-proxying
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>the list of candidate advisors</returns>
protected override IList FindCandidateAdvisors(Type targetType, string targetName)
{
if (cachedAdvisors == null) {
cachedAdvisors = base.FindCandidateAdvisors(targetType, targetName);
}
return cachedAdvisors;
}
/// <summary>
/// Whether the given advisor is eligible for the specified target.
@@ -109,5 +126,14 @@ namespace Spring.Aop.Framework.AutoProxy
{
return (!usePrefix || advisorName.StartsWith(advisorObjectNamePrefix));
}
}
/// <summary>
/// Validate configuration
/// </summary>
public virtual void AfterPropertiesSet()
{
// eagerly resolve advisors at this stage already to prevent circular dep problems.
// TODO (EE): fix instantiation process to make test "AdvisorAutoProxyCreatorCircularReferencesTests" work.
cachedAdvisors = base.FindCandidateAdvisors(null, null);
}
}

View File

@@ -33,6 +33,7 @@ using Spring.Objects.Events;
using Spring.Objects.Events.Support;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Objects.Support;
using Spring.Util;
@@ -75,7 +76,7 @@ namespace Spring.Context.Support
/// <seealso cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>
/// <seealso cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>
public abstract class AbstractApplicationContext
: ConfigurableResourceLoader, IConfigurableApplicationContext
: ConfigurableResourceLoader, IConfigurableApplicationContext, IObjectDefinitionRegistry
{
#region Constants
@@ -124,7 +125,7 @@ namespace Spring.Context.Support
/// <summary>
/// The <see cref="Common.Logging.ILog"/> instance for this class.
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(AbstractApplicationContext));
protected readonly ILog log;
/// <summary>
/// The <see cref="Spring.Context.IMessageSource"/> instance we delegate
@@ -140,10 +141,10 @@ namespace Spring.Context.Support
private IApplicationContext _parentApplicationContext;
private readonly IList _objectFactoryPostProcessors;
private IList _defaultObjectPostProcessors;
private readonly IList _defaultObjectPostProcessors;
private string _name;
private DateTime _startupDate;
private readonly bool _caseSensitive;
private readonly bool _isCaseSensitive;
#endregion
@@ -196,8 +197,10 @@ namespace Spring.Context.Support
protected AbstractApplicationContext(string name, bool caseSensitive,
IApplicationContext parentApplicationContext)
{
log = LogManager.GetLogger(this.GetType());
_name = (StringUtils.IsNullOrEmpty(name)) ? DefaultRootContextName : name;
_caseSensitive = caseSensitive;
_isCaseSensitive = caseSensitive;
_parentApplicationContext = parentApplicationContext;
_objectFactoryPostProcessors = new ArrayList();
_defaultObjectPostProcessors = new ArrayList();
@@ -294,9 +297,9 @@ namespace Spring.Context.Support
/// Gets a flag indicating whether context should be case sensitive.
/// </summary>
/// <value><c>true</c> if object lookups are case sensitive; otherwise, <c>false</c>.</value>
protected bool CaseSensitive
public bool IsCaseSensitive
{
get { return _caseSensitive; }
get { return _isCaseSensitive; }
}
/// <summary>
@@ -1517,6 +1520,9 @@ namespace Spring.Context.Support
/// This is an alternative to <code>ContainsObject</code>, ignoring an object
/// of the given name from an ancestor object factory.
/// </summary>
/// <remarks>
///
/// </remarks>
/// <param name="name">The name of the object to query.</param>
/// <returns>
/// <c>true</c> if objects with the specified name is defined in the local factory; otherwise, <c>false</c>.
@@ -1528,6 +1534,60 @@ namespace Spring.Context.Support
#endregion
#region IObjectDefinitionRegistry Members
/// <summary>
/// Determine whether the given object name is already in use within this context,
/// i.e. whether there is a local object. May be override by subclasses, the default
/// implementation simply returns <see cref="ContainsLocalObject"/>
/// </summary>
public virtual bool IsObjectNameInUse(string objectName)
{
return ContainsLocalObject(objectName);
}
/// <summary>
/// Register a new object definition with this registry.
/// Must support
/// <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>
/// and <see cref="Spring.Objects.Factory.Support.ChildObjectDefinition"/>.
/// </summary>
/// <param name="name">The name of the object instance to register.</param>
/// <param name="definition">The definition of the object instance to register.</param>
/// <remarks>
/// <p>
/// Must support
/// <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/> and
/// <see cref="Spring.Objects.Factory.Support.ChildObjectDefinition"/>.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object definition is invalid.
/// </exception>
public virtual void RegisterObjectDefinition(string name, IObjectDefinition definition)
{
ObjectFactory.RegisterObjectDefinition(name, definition);
}
/// <summary>
/// Given a object name, create an alias. We typically use this method to
/// support names that are illegal within XML ids (used for object names).
/// </summary>
/// <param name="name">The name of the object.</param>
/// <param name="theAlias">The alias that will behave the same as the object name.</param>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there is no object with the given name.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectDefinitionStoreException">
/// If the alias is already in use.
/// </exception>
public virtual void RegisterAlias(string name, string theAlias)
{
ObjectFactory.RegisterAlias(name, theAlias);
}
#endregion
#region IMessageSource Members
/// <summary>
@@ -1896,12 +1956,14 @@ namespace Spring.Context.Support
private sealed class ObjectPostProcessorChecker : IObjectPostProcessor, IOrdered
{
private readonly ILog log;
private int _objectPostProcessorTargetCount;
private IConfigurableListableObjectFactory _objectFactory;
public ObjectPostProcessorChecker()
{
log = LogManager.GetLogger(this.GetType());
}
public void Reset(IConfigurableListableObjectFactory objectFactory, int objectPostProcessorTargetCount)

View File

@@ -1,5 +1,5 @@
#region License
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
@@ -14,228 +14,226 @@
* 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.IO;
using Common.Logging;
using Spring.Objects;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.Util;
#endregion
namespace Spring.Context.Support
{
/// <summary>
/// Convenient abstract superclass for
/// <see cref="Spring.Context.IApplicationContext"/> implementations that
/// draw their configuration from XML documents containing object
/// definitions as understood by an
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/>.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Griffin Caprio (.NET)</author>
public abstract class AbstractXmlApplicationContext : AbstractApplicationContext
{
/// <summary>
/// The <see cref="Common.Logging.ILog"/> instance for this class.
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(AbstractXmlApplicationContext));
private DefaultListableObjectFactory _objectFactory;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is an <see langword="abstract"/> class, and as such exposes
/// no public constructors.
/// </p>
/// </remarks>
protected AbstractXmlApplicationContext() : this(null, true, null)
{}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext"/> class
/// with the given parent context.
/// </summary>
/// <remarks>
/// <p>
/// This is an <see langword="abstract"/> class, and as such exposes
/// no public constructors.
/// </p>
/// </remarks>
/// <param name="name">The application context name.</param>
/// <param name="caseSensitive">Flag specifying whether to make this context case sensitive or not.</param>
/// <param name="parentContext">The parent context.</param>
protected AbstractXmlApplicationContext(string name, bool caseSensitive,
IApplicationContext parentContext) : base(name, caseSensitive, parentContext)
{}
/// <summary>
/// An array of resource locations, referring to the XML object
/// definition files that this context is to be built with.
/// </summary>
/// <remarks>
/// <p>
/// Examples of the format of the various strings that would be
/// returned by accessing this property can be found in the overview
/// documentation of with the <see cref="XmlApplicationContext"/>
/// class.
/// </p>
/// </remarks>
/// <returns>
/// An array of resource locations, or <see langword="null"/> if none.
/// </returns>
protected abstract string[] ConfigurationLocations { get; }
/// <summary>
/// Instantiates and populates the underlying
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> with the object
/// definitions yielded up by the <see cref="ConfigurationLocations"/>
/// method.
/// </summary>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors encountered while refreshing the object factory.
/// </exception>
/// <exception cref="ApplicationContextException">
/// In the case of errors encountered reading any of the resources
/// yielded by the <see cref="ConfigurationLocations"/> method.
/// </exception>
/// <seealso cref="Spring.Context.Support.AbstractApplicationContext.RefreshObjectFactory()"/>
protected override void RefreshObjectFactory()
{
// Shut down previous object factory, if any.
IConfigurableListableObjectFactory oldObjectFactory = null;
oldObjectFactory = _objectFactory;
if (oldObjectFactory != null)
{
_objectFactory = null;
oldObjectFactory.Dispose();
}
try
{
DefaultListableObjectFactory objectFactory = CreateObjectFactory();
LoadObjectDefinitions(objectFactory);
_objectFactory = objectFactory;
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Refreshed ObjectFactory for application context '{0}'.",
Name));
}
#endregion
}
catch (IOException ex)
{
throw new ApplicationContextException(
string.Format(
"I/O error parsing XML resource for application context '{0}'.",
Name), ex);
}
catch (UriFormatException ex)
{
throw new ApplicationContextException(
string.Format(
"Error parsing resource locations [{0}] for application context '{1}'.",
StringUtils.ArrayToCommaDelimitedString(ConfigurationLocations),
Name), ex);
}
}
/// <summary>
/// Initialize the object definition reader used for loading the object
/// definitions of this context.
/// </summary>
/// <remarks>
/// <p>
/// The default implementation of this method is a no-op; i.e. it does
/// nothing. Can be overridden in subclasses to provide custom
/// initialization of the supplied
/// <paramref name="objectDefinitionReader"/>; for example, a derived
/// class may want to turn off XML validation.
/// </p>
/// </remarks>
/// <param name="objectDefinitionReader">
/// The object definition reader used by this context.
/// </param>
protected virtual void InitObjectDefinitionReader(
XmlObjectDefinitionReader objectDefinitionReader)
{}
/// <summary>
/// Load the object definitions with the given
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/>.
/// </summary>
/// <remarks>
/// <p>
/// The lifecycle of the object factory is handled by
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext.RefreshObjectFactory"/>;
/// therefore this method is just supposed to load and / or register
/// object definitions.
/// </p>
/// </remarks>
/// <param name="objectDefinitionReader">
/// The reader containing object definitions.</param>
/// <exception cref="ObjectsException">
/// In case of object registration errors.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors encountered reading any of the resources
/// yielded by the <see cref="ConfigurationLocations"/> method.
/// </exception>
protected virtual void LoadObjectDefinitions(
XmlObjectDefinitionReader objectDefinitionReader)
{
string[] locations = ConfigurationLocations;
if (locations != null)
{
objectDefinitionReader.LoadObjectDefinitions(ConfigurationLocations);
}
}
/// <summary>
/// Loads the object definitions into the given object factory, typically through
/// delegating to one or more object definition readers.
/// </summary>
/// <param name="objectFactory">The object factory to lead object definitions into</param>
/// <see cref="XmlObjectDefinitionReader"/>
/// <see cref="PropertiesObjectDefinitionReader"/>
protected virtual void LoadObjectDefinitions(DefaultListableObjectFactory objectFactory)
{
//Create a new XmlObjectDefinitionReader for the given ObjectFactory
XmlObjectDefinitionReader objectDefinitionReader = CreateXmlObjectDefinitionReader(objectFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
objectDefinitionReader.ResourceLoader = this;
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the object definitions.
InitObjectDefinitionReader(objectDefinitionReader);
LoadObjectDefinitions(objectDefinitionReader);
*/
#endregion
#region Imports
using System;
using System.IO;
using System.Threading;
using Common.Logging;
using Spring.Objects;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.Util;
#endregion
namespace Spring.Context.Support
{
/// <summary>
/// Convenient abstract superclass for
/// <see cref="Spring.Context.IApplicationContext"/> implementations that
/// draw their configuration from XML documents containing object
/// definitions as understood by an
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/>.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Griffin Caprio (.NET)</author>
public abstract class AbstractXmlApplicationContext : AbstractApplicationContext
{
private DefaultListableObjectFactory _objectFactory;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is an <see langword="abstract"/> class, and as such exposes
/// no public constructors.
/// </p>
/// </remarks>
protected AbstractXmlApplicationContext()
: this(null, true, null)
{ }
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext"/> class
/// with the given parent context.
/// </summary>
/// <remarks>
/// <p>
/// This is an <see langword="abstract"/> class, and as such exposes
/// no public constructors.
/// </p>
/// </remarks>
/// <param name="name">The application context name.</param>
/// <param name="caseSensitive">Flag specifying whether to make this context case sensitive or not.</param>
/// <param name="parentContext">The parent context.</param>
protected AbstractXmlApplicationContext(string name, bool caseSensitive,
IApplicationContext parentContext)
: base(name, caseSensitive, parentContext)
{ }
/// <summary>
/// An array of resource locations, referring to the XML object
/// definition files that this context is to be built with.
/// </summary>
/// <remarks>
/// <p>
/// Examples of the format of the various strings that would be
/// returned by accessing this property can be found in the overview
/// documentation of with the <see cref="XmlApplicationContext"/>
/// class.
/// </p>
/// </remarks>
/// <returns>
/// An array of resource locations, or <see langword="null"/> if none.
/// </returns>
protected abstract string[] ConfigurationLocations { get; }
/// <summary>
/// Instantiates and populates the underlying
/// <see cref="Spring.Objects.Factory.IObjectFactory"/> with the object
/// definitions yielded up by the <see cref="ConfigurationLocations"/>
/// method.
/// </summary>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors encountered while refreshing the object factory.
/// </exception>
/// <exception cref="ApplicationContextException">
/// In the case of errors encountered reading any of the resources
/// yielded by the <see cref="ConfigurationLocations"/> method.
/// </exception>
/// <seealso cref="Spring.Context.Support.AbstractApplicationContext.RefreshObjectFactory()"/>
protected override void RefreshObjectFactory()
{
// Shut down previous object factory, if any.
IConfigurableListableObjectFactory oldObjectFactory = null;
oldObjectFactory = Interlocked.Exchange(ref _objectFactory, null);
if (oldObjectFactory != null)
{
// _objectFactory = null;
oldObjectFactory.Dispose();
}
try
{
DefaultListableObjectFactory objectFactory = CreateObjectFactory();
LoadObjectDefinitions(objectFactory);
_objectFactory = objectFactory;
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format(
"Refreshed ObjectFactory for application context '{0}'.",
Name));
}
#endregion
}
catch (IOException ex)
{
throw new ApplicationContextException(
string.Format(
"I/O error parsing XML resource for application context '{0}'.",
Name), ex);
}
catch (UriFormatException ex)
{
throw new ApplicationContextException(
string.Format(
"Error parsing resource locations [{0}] for application context '{1}'.",
StringUtils.ArrayToCommaDelimitedString(ConfigurationLocations),
Name), ex);
}
}
/// <summary>
/// Initialize the object definition reader used for loading the object
/// definitions of this context.
/// </summary>
/// <remarks>
/// <p>
/// The default implementation of this method is a no-op; i.e. it does
/// nothing. Can be overridden in subclasses to provide custom
/// initialization of the supplied
/// <paramref name="objectDefinitionReader"/>; for example, a derived
/// class may want to turn off XML validation.
/// </p>
/// </remarks>
/// <param name="objectDefinitionReader">
/// The object definition reader used by this context.
/// </param>
protected virtual void InitObjectDefinitionReader(
XmlObjectDefinitionReader objectDefinitionReader)
{ }
/// <summary>
/// Load the object definitions with the given
/// <see cref="Spring.Objects.Factory.Xml.XmlObjectDefinitionReader"/>.
/// </summary>
/// <remarks>
/// <p>
/// The lifecycle of the object factory is handled by
/// <see cref="Spring.Context.Support.AbstractXmlApplicationContext.RefreshObjectFactory"/>;
/// therefore this method is just supposed to load and / or register
/// object definitions.
/// </p>
/// </remarks>
/// <param name="objectDefinitionReader">
/// The reader containing object definitions.</param>
/// <exception cref="ObjectsException">
/// In case of object registration errors.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors encountered reading any of the resources
/// yielded by the <see cref="ConfigurationLocations"/> method.
/// </exception>
protected virtual void LoadObjectDefinitions(
XmlObjectDefinitionReader objectDefinitionReader)
{
string[] locations = ConfigurationLocations;
if (locations != null)
{
objectDefinitionReader.LoadObjectDefinitions(ConfigurationLocations);
}
}
/// <summary>
/// Loads the object definitions into the given object factory, typically through
/// delegating to one or more object definition readers.
/// </summary>
/// <param name="objectFactory">The object factory to lead object definitions into</param>
/// <see cref="XmlObjectDefinitionReader"/>
/// <see cref="PropertiesObjectDefinitionReader"/>
protected virtual void LoadObjectDefinitions(DefaultListableObjectFactory objectFactory)
{
//Create a new XmlObjectDefinitionReader for the given ObjectFactory
XmlObjectDefinitionReader objectDefinitionReader = CreateXmlObjectDefinitionReader(objectFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
objectDefinitionReader.ResourceLoader = this;
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the object definitions.
InitObjectDefinitionReader(objectDefinitionReader);
LoadObjectDefinitions(objectDefinitionReader);
}
/// <summary>
@@ -246,57 +244,60 @@ namespace Spring.Context.Support
protected virtual XmlObjectDefinitionReader CreateXmlObjectDefinitionReader(DefaultListableObjectFactory objectFactory)
{
return new XmlObjectDefinitionReader(objectFactory);
}
/// <summary>
/// Customizes the internal object factory used by this context.
/// </summary>
/// <remarks>Called for each <see cref="AbstractApplicationContext.Refresh()"/> attempt.
/// <p>
/// The default implementation is empty. Can be overriden in subclassses to customize
/// DefaultListableBeanFatory's standard settings.
/// </p></remarks>
/// <param name="objectFactory">The newly created object factory for this context</param>
protected virtual void CustomizeObjectFactory(DefaultListableObjectFactory objectFactory)
{
}
/// <summary>
/// Create an internal object factory for this context.
/// </summary>
/// <remarks>
/// <p>
/// Called for each <see cref="AbstractApplicationContext.Refresh()"/> attempt.
/// This default implementation creates a
/// <see cref="Spring.Objects.Factory.Support.DefaultListableObjectFactory"/>
/// with the internal object factory of this context's parent serving
/// as the parent object factory. Can be overridden in subclasse,s
/// for example to customize DefaultListableBeanFactory's settings.
/// </p>
/// </remarks>
/// <returns>The object factory for this context.</returns>
protected virtual DefaultListableObjectFactory CreateObjectFactory()
{
return new DefaultListableObjectFactory(CaseSensitive, GetInternalParentObjectFactory());
}
/// <summary>
/// Subclasses must return their internal object factory here.
/// </summary>
/// <returns>
/// The internal object factory for the application context.
/// </returns>
/// <seealso cref="Spring.Context.Support.AbstractApplicationContext.ObjectFactory"/>
public override IConfigurableListableObjectFactory ObjectFactory
{
get
{
lock(SyncRoot)
{
return _objectFactory;
}
}
}
}
}
/// <summary>
/// Customizes the internal object factory used by this context.
/// </summary>
/// <remarks>Called for each <see cref="AbstractApplicationContext.Refresh()"/> attempt.
/// <p>
/// The default implementation is empty. Can be overriden in subclassses to customize
/// DefaultListableBeanFatory's standard settings.
/// </p></remarks>
/// <param name="objectFactory">The newly created object factory for this context</param>
protected virtual void CustomizeObjectFactory(DefaultListableObjectFactory objectFactory)
{
// noop
}
/// <summary>
/// Create an internal object factory for this context.
/// </summary>
/// <remarks>
/// <p>
/// Called for each <see cref="AbstractApplicationContext.Refresh()"/> attempt.
/// This default implementation creates a
/// <see cref="Spring.Objects.Factory.Support.DefaultListableObjectFactory"/>
/// with the internal object factory of this context's parent serving
/// as the parent object factory. Can be overridden in subclasse,s
/// for example to customize DefaultListableBeanFactory's settings.
/// </p>
/// </remarks>
/// <returns>The object factory for this context.</returns>
protected virtual DefaultListableObjectFactory CreateObjectFactory()
{
return new DefaultListableObjectFactory(IsCaseSensitive, GetInternalParentObjectFactory());
}
/// <summary>
/// Subclasses must return their internal object factory here.
/// </summary>
/// <returns>
/// The internal object factory for the application context.
/// </returns>
/// <seealso cref="Spring.Context.Support.AbstractApplicationContext.ObjectFactory"/>
public override IConfigurableListableObjectFactory ObjectFactory
{
get { return _objectFactory; }
}
/// <summary>
/// Determine whether the given object name is already in use within this context's object factory,
/// i.e. whether there is a local object or alias registered under this name.
/// </summary>
public override bool IsObjectNameInUse(string objectName)
{
return _objectFactory.IsObjectNameInUse(objectName);
}
}
}

View File

@@ -1,5 +1,5 @@
#region License
#region License
/*
* Copyright 2002-2007 the original author or authors.
*
@@ -14,243 +14,166 @@
* 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
using System;
using Spring.Core.IO;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Util;
namespace Spring.Context.Support
{
/// <summary>
/// Generic ApplicationContext implementation that holds a single internal
/// <see cref="DefaultListableObjectFactory"/> instance and does not
/// assume a specific object definition format.
/// </summary>
/// <remarks>
/// Implements the <see cref="IObjectDefinitionRegistry"/> interface in order
/// to allow for aplying any object definition readers to it.
/// <para>Typical usage is to register a variety of object definitions via the
/// <see cref="IObjectDefinitionRegistry"/> interface and then call
/// <see cref="IConfigurableApplicationContext.Refresh"/> to initialize those
/// objects with application context semantics (handling
/// <see cref="IApplicationContextAware"/>, auto-detecting
/// <see cref="IObjectPostProcessor"/> ObjectFactoryPostProcessors, etc).
/// </para>
/// <para>In contrast to other IApplicationContext implementations that create a new internal
/// IObjectFactory instance for each refresh, the internal IObjectFactory of this context
/// is available right from the start, to be able to register object definitions on it.
/// <see cref="IConfigurableApplicationContext.Refresh"/> may only be called once</para>
/// <para>Usage examples</para>
/// <example>
/// GenericApplicationContext ctx = new GenericApplicationContext();
///
/// </example>
/// </remarks>
/// <author>Mark Pollack</author>
public class GenericApplicationContext : AbstractApplicationContext, IObjectDefinitionRegistry
{
private DefaultListableObjectFactory objectFactory;
private bool refreshed = false;
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
public GenericApplicationContext()
{
objectFactory = new DefaultListableObjectFactory();
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="caseSensitive">if set to <c>true</c> names in the context are case sensitive.</param>
public GenericApplicationContext(bool caseSensitive)
{
objectFactory = new DefaultListableObjectFactory(caseSensitive);
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="objectFactory">The object factory instance to use for this context.</param>
public GenericApplicationContext(DefaultListableObjectFactory objectFactory)
{
AssertUtils.ArgumentNotNull(objectFactory, "objectFactory", "ObjectFactory must not be null");
this.objectFactory = objectFactory;
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="parent">The parent application context.</param>
public GenericApplicationContext(IApplicationContext parent)
{
objectFactory = new DefaultListableObjectFactory();
ParentContext = parent;
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="name">The name of the application context.</param>
/// <param name="caseSensitive">if set to <c>true</c> names in the context are case sensitive.</param>
/// <param name="parent">The parent application context.</param>
public GenericApplicationContext(string name, bool caseSensitive, IApplicationContext parent) : this(caseSensitive)
{
Name = name;
ParentContext = parent;
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="objectFactory">The object factory to use for this context</param>
/// <param name="parent">The parent applicaiton context.</param>
public GenericApplicationContext(DefaultListableObjectFactory objectFactory, IApplicationContext parent) : this(objectFactory)
{
ParentContext = parent;
}
/// <summary>
/// Gets the parent context, or <see langword="null"/> if there is no
/// parent context. Set the parent of this application context also setting
/// the parent of the interanl ObjectFactory accordingly.
/// </summary>
/// <value>The parent context</value>
/// <returns>
/// The parent context, or <see langword="null"/> if there is no
/// parent.
/// </returns>
/// <seealso cref="Spring.Context.IApplicationContext.ParentContext"/>
public override IApplicationContext ParentContext
{
get
{
return base.ParentContext;
}
set {
base.ParentContext = value;
objectFactory.ParentObjectFactory = GetInternalParentObjectFactory();
}
}
/// <summary>
/// Do nothing operation. We hold a single internal ObjectFactory and rely on callers
/// to register objects throug our public methods (or the ObjectFactory's).
/// </summary>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors encountered while refreshing the object factory.
/// </exception>
protected override void RefreshObjectFactory()
{
if (refreshed)
{
throw new InvalidOperationException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
refreshed = true;
}
/// <summary>
/// Return the internal object factory of this application context.
/// </summary>
/// <value></value>
public override IConfigurableListableObjectFactory ObjectFactory
{
get { return objectFactory; }
}
/// <summary>
/// Gets the underlying object factory of this context, available for
/// registering object definitions.
/// </summary>
/// <remarks>You need to call <code>Refresh</code> to initialize the
/// objects factory and its contained objects with application context
/// semantics (autodecting IObjectFactoryPostProcessors, etc).</remarks>
/// <value>The internal object factory (as DefaultListableObjectFactory).</value>
public DefaultListableObjectFactory DefaultListableObjectFactory
{
get { return objectFactory; }
}
#region IObjectDefinitionRegistry Members
/// <summary>
/// Returns the
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/>
/// for the given object name.
/// </summary>
/// <param name="name">The name of the object to find a definition for.</param>
/// <returns>
/// The <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/> for
/// the given name (never null).
/// </returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If the object definition cannot be resolved.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of errors.
/// </exception>
public override IObjectDefinition GetObjectDefinition(string name)
{
return objectFactory.GetObjectDefinition(name);
}
/// <summary>
/// Register a new object definition with this registry.
/// Must support
/// <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>
/// and <see cref="Spring.Objects.Factory.Support.ChildObjectDefinition"/>.
/// </summary>
/// <param name="name">The name of the object instance to register.</param>
/// <param name="definition">The definition of the object instance to register.</param>
/// <remarks>
/// <p>
/// Must support
/// <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/> and
/// <see cref="Spring.Objects.Factory.Support.ChildObjectDefinition"/>.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object definition is invalid.
/// </exception>
public void RegisterObjectDefinition(string name, IObjectDefinition definition)
{
objectFactory.RegisterObjectDefinition(name, definition);
}
/// <summary>
/// Given a object name, create an alias. We typically use this method to
/// support names that are illegal within XML ids (used for object names).
/// </summary>
/// <param name="name">The name of the object.</param>
/// <param name="theAlias">The alias that will behave the same as the object name.</param>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there is no object with the given name.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectDefinitionStoreException">
/// If the alias is already in use.
/// </exception>
public void RegisterAlias(string name, string theAlias)
{
objectFactory.RegisterAlias(name, theAlias);
*/
#endregion
using System;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Util;
namespace Spring.Context.Support
{
/// <summary>
/// Generic ApplicationContext implementation that holds a single internal
/// <see cref="DefaultListableObjectFactory"/> instance and does not
/// assume a specific object definition format.
/// </summary>
/// <remarks>
/// Implements the <see cref="IObjectDefinitionRegistry"/> interface in order
/// to allow for aplying any object definition readers to it.
/// <para>Typical usage is to register a variety of object definitions via the
/// <see cref="IObjectDefinitionRegistry"/> interface and then call
/// <see cref="IConfigurableApplicationContext.Refresh"/> to initialize those
/// objects with application context semantics (handling
/// <see cref="IApplicationContextAware"/>, auto-detecting
/// <see cref="IObjectPostProcessor"/> ObjectFactoryPostProcessors, etc).
/// </para>
/// <para>In contrast to other IApplicationContext implementations that create a new internal
/// IObjectFactory instance for each refresh, the internal IObjectFactory of this context
/// is available right from the start, to be able to register object definitions on it.
/// <see cref="IConfigurableApplicationContext.Refresh"/> may only be called once</para>
/// <para>Usage examples</para>
/// <example>
/// GenericApplicationContext ctx = new GenericApplicationContext();
/// // register your objects and object definitions
/// ctx.RegisterObjectDefinition(...)
/// ctx.Refresh();
/// </example>
/// </remarks>
/// <author>Mark Pollack</author>
public class GenericApplicationContext : AbstractApplicationContext
{
private readonly DefaultListableObjectFactory objectFactory;
private bool refreshed = false;
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
public GenericApplicationContext()
: this(null, true, null, new DefaultListableObjectFactory())
{
// noop
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="caseSensitive">if set to <c>true</c> names in the context are case sensitive.</param>
public GenericApplicationContext(bool caseSensitive)
: this(null, caseSensitive, null, new DefaultListableObjectFactory())
{
// noop
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="objectFactory">The object factory instance to use for this context.</param>
public GenericApplicationContext(DefaultListableObjectFactory objectFactory)
: this(null, true, null, objectFactory)
{
// noop
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="parent">The parent application context.</param>
public GenericApplicationContext(IApplicationContext parent)
: this(null, true, parent, new DefaultListableObjectFactory())
{
// noop
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="name">The name of the application context.</param>
/// <param name="caseSensitive">if set to <c>true</c> names in the context are case sensitive.</param>
/// <param name="parent">The parent application context.</param>
public GenericApplicationContext(string name, bool caseSensitive, IApplicationContext parent)
: this(name, caseSensitive, parent, new DefaultListableObjectFactory())
{
// noop
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="objectFactory">The object factory to use for this context</param>
/// <param name="parent">The parent applicaiton context.</param>
public GenericApplicationContext(DefaultListableObjectFactory objectFactory, IApplicationContext parent)
: this(null, true, parent, objectFactory)
{
// noop
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericApplicationContext"/> class.
/// </summary>
/// <param name="name">The name of the application context.</param>
/// <param name="caseSensitive">if set to <c>true</c> names in the context are case sensitive.</param>
/// <param name="parent">The parent application context.</param>
/// <param name="objectFactory">The object factory to use for this context</param>
public GenericApplicationContext(string name, bool caseSensitive, IApplicationContext parent, DefaultListableObjectFactory objectFactory)
: base(name, caseSensitive, parent)
{
AssertUtils.ArgumentNotNull(objectFactory, "objectFactory", "ObjectFactory must not be null");
this.objectFactory = objectFactory;
this.objectFactory.ParentObjectFactory = base.GetInternalParentObjectFactory();
}
/// <summary>
/// Do nothing operation. We hold a single internal ObjectFactory and rely on callers
/// to register objects throug our public methods (or the ObjectFactory's).
/// </summary>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors encountered while refreshing the object factory.
/// </exception>
protected override void RefreshObjectFactory()
{
if (refreshed)
{
throw new InvalidOperationException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
refreshed = true;
}
/// <summary>
/// Return the internal object factory of this application context.
/// </summary>
/// <value></value>
public override IConfigurableListableObjectFactory ObjectFactory
{
get { return objectFactory; }
}
/// <summary>
/// Gets the underlying object factory of this context, available for
/// registering object definitions.
/// </summary>
/// <remarks>You need to call <code>Refresh</code> to initialize the
/// objects factory and its contained objects with application context
/// semantics (autodecting IObjectFactoryPostProcessors, etc).</remarks>
/// <value>The internal object factory (as DefaultListableObjectFactory).</value>
public DefaultListableObjectFactory DefaultListableObjectFactory
{
get { return objectFactory; }
}
/// <summary>
@@ -258,11 +181,9 @@ namespace Spring.Context.Support
/// i.e. whether there is a local object or alias registered under this name or
/// an inner object created with this name.
/// </summary>
public bool IsObjectNameInUse(string objectName)
public override bool IsObjectNameInUse(string objectName)
{
return objectFactory.IsObjectNameInUse(objectName);
}
#endregion
}
}
}
}

View File

@@ -50,8 +50,8 @@ namespace Spring.Objects.Factory.Config
/// <author>Juergen Hoeller</author>
/// <author>Rick Evans (.NET)</author>
public interface IConfigurableObjectFactory : IHierarchicalObjectFactory, ISingletonObjectRegistry
{
/// <summary>
{
/// <summary>
/// Set the parent of this object factory.
/// </summary>
/// <remarks>

View File

@@ -47,7 +47,7 @@ namespace Spring.Objects.Factory
/// <summary>
/// Determines whether the local object factory contains a bean of the given name,
/// ignoring object defined in ancestor contexts.
/// ignoring object defined in ancestor contexts, also resolving a given alias if necessary.
/// This is an alternative to <code>ContainsObject</code>, ignoring an object
/// of the given name from an ancestor object factory.
/// </summary>

View File

@@ -57,8 +57,8 @@ namespace Spring.Objects.Factory
/// <author>Rod Johnson</author>
/// <author>Rick Evans (.NET)</author>
public interface IListableObjectFactory : IObjectFactory
{
/// <summary>
{
/// <summary>
/// Check if this object factory contains an object definition with the given name.
/// </summary>
/// <remarks>

View File

@@ -150,7 +150,12 @@ namespace Spring.Objects.Factory
/// <author>Rick Evans (.NET)</author>
public interface IObjectFactory : IDisposable
{
/// <summary>
/// <summary>
/// Determine whether this object factory treats object names case-sensitive or not.
/// </summary>
bool IsCaseSensitive { get; }
/// <summary>
/// Is this object a singleton?
/// </summary>
/// <remarks>
@@ -196,8 +201,8 @@ namespace Spring.Objects.Factory
/// </summary>
/// <remarks>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// The concrete lookup strategy depends on the implementation. E.g. <see cref="IHierarchicalObjectFactory"/>s
/// will also search their parent factory if a name isn't found .
/// </para>
/// </remarks>
/// <param name="name">The name of the object to query.</param>

View File

@@ -79,7 +79,7 @@ namespace Spring.Objects.Factory.Support
/// <summary>
/// The <see cref="Common.Logging.ILog"/> instance for this class.
/// </summary>
private readonly ILog log = LogManager.GetLogger(typeof(AbstractAutowireCapableObjectFactory));
private readonly ILog log;
#region Constructor (s) / Destructor
@@ -113,6 +113,8 @@ namespace Spring.Objects.Factory.Support
protected AbstractAutowireCapableObjectFactory(bool caseSensitive, IObjectFactory parentFactory)
: base(caseSensitive, parentFactory)
{
log = LogManager.GetLogger(this.GetType());
this.IgnoreDependencyInterface(typeof(IObjectFactoryAware));
this.IgnoreDependencyInterface(typeof(IObjectNameAware));
}

View File

@@ -44,10 +44,9 @@ namespace Spring.Objects.Factory.Support
#region Constants
/// <summary>
/// The shared <see cref="Common.Logging.ILog"/> instance for this class (and derived classes).
/// The <see cref="Common.Logging.ILog"/> instance for this class (and derived classes).
/// </summary>
protected static readonly ILog log =
LogManager.GetLogger(typeof (AbstractObjectDefinitionReader));
protected readonly ILog log;
#endregion
@@ -94,6 +93,8 @@ namespace Spring.Objects.Factory.Support
IObjectDefinitionRegistry registry,
AppDomain domain)
{
log = LogManager.GetLogger(this.GetType());
AssertUtils.ArgumentNotNull(registry, "registry", "IObjectDefinitionRegistry must not be null");
_registry = registry;
_domain = domain;

View File

@@ -89,19 +89,22 @@ namespace Spring.Objects.Factory.Support
/// </summary>
private static readonly object CURRENTLY_IN_CREATION = new Object();
/// <summary>
/// The <see cref="Common.Logging.ILog"/> instance for this class.
/// </summary>
private readonly ILog log = LogManager.GetLogger(typeof(AbstractObjectFactory));
/// <summary>
/// Used as value in hashtable that keeps track of singleton names currently in the
/// process of being created. Would not be necessary if we created a case insensitive implementation of
/// ISet.
/// </summary>
private static object emptyObject = new object();
private static readonly object emptyObject = new object();
/// <summary>
/// The <see cref="Common.Logging.ILog"/> instance for this class.
/// </summary>
private readonly ILog log;
/// <summary>
/// Cache of singleton objects created by <see cref="IFactoryObject"/>s: FactoryObject name -> product
/// </summary>
private readonly Hashtable factoryObjectProductCache = new Hashtable();
#region Constructor (s) / Destructor
@@ -730,63 +733,128 @@ namespace Spring.Objects.Factory.Support
/// <returns>
/// The singleton instance of the object.
/// </returns>
[Obsolete("")]
protected internal virtual object GetObjectForInstance(string name, object instance)
{
//string objectName = TransformedObjectName(name);
return GetObjectForInstance(instance, name, TransformedObjectName(name), null);
}
/// <summary>
/// Get the object for the given object instance, either the object
/// instance itself or its created object in case of an
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>.
/// </summary>
/// <param name="instance">The object instance.</param>
/// <param name="name">
/// The name that may include the factory dereference prefix (=the requested name).
/// </param>
/// <param name="canonicalName">
/// The canonical object name
/// </param>
/// <param name="rod">the merged object definition</param>
/// <returns>
/// The singleton instance of the object.
/// </returns>
protected internal virtual object GetObjectForInstance(object instance, string name, string canonicalName, RootObjectDefinition rod)
{
// don't let calling code try to dereference the
// object factory if the object isn't a factory
if (IsFactoryDereference(name) && !(instance is IFactoryObject))
if (IsFactoryDereference(name) && !(ObjectUtils.IsAssignable(typeof (IFactoryObject), instance)))
{
throw new ObjectIsNotAFactoryException(TransformedObjectName(name), instance);
throw new ObjectIsNotAFactoryException(canonicalName, instance);
}
// now we have the object instance, which may be a normal object
// or an IFactoryObject. If it's an IFactoryObject, we use it to
// create an object instance, unless the caller actually wants
// a reference to the factory.
if (ObjectUtils.IsAssignableAndNotTransparentProxy(typeof(IFactoryObject), instance))
// or an IFactoryObject. If it's an IFactoryObject and the caller wants
// a reference to the factory there's nothing more to do
// it's a normal object ?
if (!ObjectUtils.IsAssignable(typeof (IFactoryObject), instance))
{
if (!IsFactoryDereference(name))
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Calling code asked for normal instance for name '{0}'.", canonicalName));
}
// return object instance from factory...
IFactoryObject factory = (IFactoryObject)instance;
string objectName = TransformedObjectName(name);
#endregion
#region Instrumentation
return instance;
}
if (log.IsDebugEnabled)
// the user wants the factory itself ?
if (!ObjectUtils.IsAssignable(typeof (IFactoryObject), instance) || IsFactoryDereference(name))
{
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(
string.Format("Calling code asked for IFactoryObject instance for name '{0}'.",
TransformedObjectName(name)));
}
#endregion
return instance;
}
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Object with name '{0}' is a factory object.", canonicalName));
}
#endregion
object resultInstance = null;
if (rod == null)
{
resultInstance = factoryObjectProductCache[canonicalName];
}
if (resultInstance == null)
{
// return object instance from factory...
IFactoryObject factory = (IFactoryObject) instance;
if (rod == null && ContainsObjectDefinition(canonicalName))
{
rod = GetMergedObjectDefinition(canonicalName, true);
}
if (factory.IsSingleton && ContainsSingleton(canonicalName))
{
lock (factoryObjectProductCache)
{
log.Debug(string.Format("Object with name '{0}' is a factory object.", objectName));
}
#endregion
RootObjectDefinition rod =
(ContainsObjectDefinition(objectName) ? GetMergedObjectDefinition(objectName, true) : null);
instance = GetObjectFromFactoryObject(factory, objectName, rod);
if (instance == null)
{
throw new FactoryObjectNotInitializedException(TransformedObjectName(name),
"Factory object returned null object - "
+ "possible cause: not fully initialized due to "
+ "circular object reference.");
resultInstance = factoryObjectProductCache[canonicalName];
if (resultInstance == null)
{
resultInstance = GetObjectFromFactoryObject(factory, canonicalName, rod);
if (resultInstance != null)
{
factoryObjectProductCache.Add(canonicalName, resultInstance);
}
return resultInstance;
}
}
}
else
resultInstance = GetObjectFromFactoryObject(factory, canonicalName, rod);
if (resultInstance == null)
{
// the user wants the factory itself...
if (log.IsDebugEnabled)
{
log.Debug(
string.Format("Calling code asked for IFactoryObject instance for name '{0}'.",
TransformedObjectName(name)));
}
throw new FactoryObjectNotInitializedException(canonicalName,
"Factory object returned null object - "
+ "possible cause: not fully initialized due to "
+ "circular object reference.");
}
}
return instance;
return resultInstance;
}
/// <summary>
@@ -1836,7 +1904,7 @@ namespace Spring.Objects.Factory.Support
#endregion
instance = GetObjectForInstance(name, sharedInstance);
instance = GetObjectForInstance(sharedInstance, name, objectName, null);
return EnsureObjectIsOfRequiredType(name, instance, requiredType);
}
}
@@ -1877,7 +1945,7 @@ namespace Spring.Objects.Factory.Support
{
// create object instance...
object sharedInstance = CreateAndCacheSingletonInstance(objectName, mergedObjectDefinition, arguments);
instance = GetObjectForInstance(name, sharedInstance);
instance = GetObjectForInstance(sharedInstance, name, objectName, mergedObjectDefinition);
}
else
{

View File

@@ -269,7 +269,7 @@ namespace Spring.Objects.Factory.Support
{
//SPRNET-986 ObjectUtils.EmptyObjects -> null
instance = objectFactory.InstantiateObject(actualInnerObjectName, mod, null, false, false);
result = objectFactory.GetObjectForInstance(actualInnerObjectName, instance);
result = objectFactory.GetObjectForInstance(instance, actualInnerObjectName, actualInnerObjectName, mod);
}
catch (ObjectsException ex)
{

View File

@@ -58,6 +58,14 @@ namespace Spring.Objects.Factory.Support
/// </summary>
private Hashtable objects = new Hashtable();
/// <summary>
/// Determine whether this object factory treats object names case-sensitive or not.
/// </summary>
public bool IsCaseSensitive
{
get { return true; }
}
/// <summary>
/// Return the number of objects defined in the factory.
/// </summary>

View File

@@ -25,6 +25,7 @@ using System.Collections;
using System.Globalization;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Proxies;
using Common.Logging;
using Spring.Objects;
using Spring.Reflection.Dynamic;
@@ -311,8 +312,32 @@ namespace Spring.Util
/// <returns>True if the type is assignable from the value.</returns>
public static bool IsAssignable(Type type, object obj)
{
AssertUtils.ArgumentNotNull(type, "type");
if (!type.IsPrimitive && obj == null)
{
return true;
}
if (RemotingServices.IsTransparentProxy(obj))
{
RealProxy rp = RemotingServices.GetRealProxy(obj);
if (rp is IRemotingTypeInfo)
{
return ((IRemotingTypeInfo) rp).CanCastTo(type, obj);
}
else if (rp != null)
{
type = rp.GetProxiedType();
}
if (type == null)
{
// cannot decide
return false;
}
}
return (type.IsInstanceOfType(obj) ||
(!type.IsPrimitive && obj == null) ||
(type.Equals(typeof(bool)) && obj is Boolean) ||
(type.Equals(typeof(byte)) && obj is Byte) ||
(type.Equals(typeof(char)) && obj is Char) ||

View File

@@ -57,11 +57,6 @@ namespace Spring.Context.Support
/// <author>Aleksandar Seovic</author>
public class WebApplicationContext : AbstractXmlApplicationContext
{
/// <summary>
/// The <see cref="Common.Logging.ILog"/> instance for this class.
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(WebApplicationContext));
// holds construction info for debugging output
private DateTime _constructionTimeStamp;
private string _constructionUrl;
@@ -133,6 +128,8 @@ namespace Spring.Context.Support
static WebApplicationContext()
{
ILog s_weblog = LogManager.GetLogger(typeof(WebApplicationContext));
// register for ContextRegistry.Cleared event - we need to discard our cache in this case
ContextRegistry.Cleared += new EventHandler(OnContextRegistryCleared);
@@ -153,23 +150,23 @@ namespace Spring.Context.Support
typeof(HttpRuntime).GetField("_beforeFirstRequest", BindingFlags.Instance | BindingFlags.NonPublic).
GetValue(runtime);
}
log.Debug("BeforeFirstRequest:" + beforeFirstRequest);
s_weblog.Debug("BeforeFirstRequest:" + beforeFirstRequest);
if (beforeFirstRequest)
{
try
{
string firstRequestPath = HttpRuntime.AppDomainAppVirtualPath.TrimEnd('/') + "/dummy.context";
log.Info("Forcing first request " + firstRequestPath);
s_weblog.Info("Forcing first request " + firstRequestPath);
SafeMethod fnProcessRequestNow = new SafeMethod(typeof(HttpRuntime).GetMethod("ProcessRequestNow", BindingFlags.Static|BindingFlags.NonPublic));
SimpleWorkerRequest wr = new SimpleWorkerRequest(firstRequestPath, string.Empty, new StringWriter());
fnProcessRequestNow.Invoke(null, new object[] { wr });
// HttpRuntime.ProcessRequest(
// wr);
log.Info("Successfully processed first request!");
s_weblog.Info("Successfully processed first request!");
}
catch (Exception ex)
{
log.Error("Failed processing first request", ex);
s_weblog.Error("Failed processing first request", ex);
throw;
}
}
@@ -184,9 +181,10 @@ namespace Spring.Context.Support
{
lock (s_webContextCache)
{
if (log.IsDebugEnabled)
ILog s_weblog = LogManager.GetLogger(typeof(WebApplicationContext));
if (s_weblog.IsDebugEnabled)
{
log.Debug("received ContextRegistry.Cleared event - clearing webContextCache");
s_weblog.Debug("received ContextRegistry.Cleared event - clearing webContextCache");
}
s_webContextCache.Clear();
}
@@ -229,20 +227,23 @@ namespace Spring.Context.Support
contextName = DefaultRootContextName;
}
ILog s_weblog = LogManager.GetLogger(typeof(WebApplicationContext));
bool isLogDebugEnabled = s_weblog.IsDebugEnabled;
lock (s_webContextCache)
{
if (log.IsDebugEnabled)
if (isLogDebugEnabled)
{
log.Debug(string.Format("looking up web context '{0}' in WebContextCache", contextName));
s_weblog.Debug(string.Format("looking up web context '{0}' in WebContextCache", contextName));
}
// first lookup in our own cache
IApplicationContext context = (IApplicationContext) s_webContextCache[contextName];
if (context != null)
{
// found - nothing to do anymore
if (log.IsDebugEnabled)
if (isLogDebugEnabled)
{
log.Debug(
s_weblog.Debug(
string.Format("returning WebContextCache hit '{0}' for vpath '{1}' ", context, contextName));
}
return context;
@@ -251,9 +252,9 @@ namespace Spring.Context.Support
// lookup ContextRegistry
lock (ContextRegistry.SyncRoot)
{
if (log.IsDebugEnabled)
if (isLogDebugEnabled)
{
log.Debug(string.Format("looking up web context '{0}' in ContextRegistry", contextName));
s_weblog.Debug(string.Format("looking up web context '{0}' in ContextRegistry", contextName));
}
if (ContextRegistry.IsContextRegistered(contextName))
@@ -266,9 +267,9 @@ namespace Spring.Context.Support
// finally ask HttpConfigurationSystem for the requested context
try
{
if (log.IsDebugEnabled)
if (isLogDebugEnabled)
{
log.Debug(
s_weblog.Debug(
string.Format(
"web context for vpath '{0}' not found. Force creation using filepath '{1}'",
contextName, virtualPath));
@@ -282,20 +283,20 @@ namespace Spring.Context.Support
if (context != null)
{
if (log.IsDebugEnabled)
log.Debug(string.Format("got context '{0}' for vpath '{1}'", context, contextName));
if (isLogDebugEnabled)
s_weblog.Debug(string.Format("got context '{0}' for vpath '{1}'", context, contextName));
}
else
{
if (log.IsDebugEnabled)
log.Debug(string.Format("no context defined for vpath '{0}'", contextName));
if (isLogDebugEnabled)
s_weblog.Debug(string.Format("no context defined for vpath '{0}'", contextName));
}
}
catch (Exception ex)
{
if (log.IsErrorEnabled)
if (s_weblog.IsErrorEnabled)
{
log.Error(string.Format("failed creating context '{0}'", contextName), ex);
s_weblog.Error(string.Format("failed creating context '{0}'", contextName), ex);
}
#if NET_1_1
if (ConfigurationUtils.IsConfigurationException(ex))
@@ -314,9 +315,9 @@ namespace Spring.Context.Support
// add it to the cache
// Note: use 'contextName' not 'context.Name' here - the same context may be used for different paths!
s_webContextCache.Add(contextName, context);
if (log.IsDebugEnabled)
if (isLogDebugEnabled)
{
log.Debug(
s_weblog.Debug(
string.Format("added context '{0}' to WebContextCache for vpath '{1}'", context, contextName));
}
@@ -329,9 +330,9 @@ namespace Spring.Context.Support
if (!s_webContextCache.ContainsKey(parentContext.Name))
{
s_webContextCache.Add(parentContext.Name, parentContext);
if (log.IsDebugEnabled)
if (isLogDebugEnabled)
{
log.Debug(
s_weblog.Debug(
string.Format("added parent context '{0}' to WebContextCache for vpath '{1}'",
parentContext, parentContext.Name));
}
@@ -369,7 +370,7 @@ namespace Spring.Context.Support
protected override DefaultListableObjectFactory CreateObjectFactory()
{
string contextPath = GetContextPathWithTrailingSlash();
return new WebObjectFactory(contextPath, this.CaseSensitive, GetInternalParentObjectFactory());
return new WebObjectFactory(contextPath, this.IsCaseSensitive, GetInternalParentObjectFactory());
}
/// <summary>

View File

@@ -22,6 +22,7 @@
using System;
using System.Reflection;
using Common.Logging;
using NUnit.Framework;
using Spring.Aop.Framework.DynamicProxy;
using Spring.Aop.Support;
@@ -45,23 +46,67 @@ namespace Spring.Aop.Framework.AutoProxy
public void TestAutoProxyCreation()
{
XmlApplicationContext context = new XmlApplicationContext(ReadOnlyXmlTestResource.GetFilePath("advisorAutoProxyCreatorCircularReferencesTests.xml", typeof(AdvisorAutoProxyCreatorCircularReferencesTests)));
CountingAfterReturningAdvisor countingAdvisor = (CountingAfterReturningAdvisor)context.GetObject("testAdvisor");
// direct deps of AutoProxyCreator are not eligable for proxying
Assert.IsFalse(AopUtils.IsAopProxy(context.GetObject("aapc")));
Assert.IsFalse(AopUtils.IsAopProxy(context.GetObject("testAdvisor")));
Assert.IsFalse(AopUtils.IsAopProxy(context.GetObject("&testObjectFactory")));
Assert.IsFalse(AopUtils.IsAopProxy(countingAdvisor));
TestObjectFactoryObject testObjectFactory = (TestObjectFactoryObject) context.GetObject("&testObjectFactory");
Assert.IsFalse(AopUtils.IsAopProxy(testObjectFactory));
Assert.IsFalse(AopUtils.IsAopProxy(context.GetObject("someOtherObject")));
// this one is completely independent
Assert.IsTrue(AopUtils.IsAopProxy(context.GetObject("independentObject")));
// products of the factory created at runtime should be proxied
Assert.IsFalse(AopUtils.IsAopProxy(context.GetObject("testObjectFactory")));
// Asserts SPRNET-1225 - advisor dependencies most not be auto-proxied
object testObject = context.GetObject("testObjectFactory");
Assert.IsFalse(AopUtils.IsAopProxy(testObject));
// Asserts SPRNET-1224 - factory product most be cached
context.GetObject("testObjectFactory");
testObjectFactory.GetObjectCounter = 0;
context.GetObject("testObjectFactory");
Assert.AreEqual(0, testObjectFactory.GetObjectCounter);
ICloneable someOtherObject = (ICloneable) context.GetObject("someOtherObject");
someOtherObject.Clone();
ICloneable independentObject = (ICloneable) context.GetObject("independentObject");
independentObject.Clone();
Assert.AreEqual(1, countingAdvisor.GetCalls());
}
}
#region Support Classes
public class TestAdvisor : StaticMethodMatcherPointcutAdvisor
public class TestDefaultAdvisorAutoProxyCreator : DefaultAdvisorAutoProxyCreator, IInitializingObject
{
private readonly ILog _logger;
public TestDefaultAdvisorAutoProxyCreator()
{
_logger = LogManager.GetLogger(this.GetType().Name + "#" + GetHashCode());
_logger.Trace("Created instance");
}
protected override object[] GetAdvicesAndAdvisorsForObject(Type targetType, string targetName, ITargetSource customTargetSource)
{
_logger.Trace("GetAdvicesAndAdvisorsForObject begin");
object[] advices = base.GetAdvicesAndAdvisorsForObject(targetType, targetName, customTargetSource);
_logger.Trace("GetAdvicesAndAdvisorsForObject end");
return advices;
}
public override void AfterPropertiesSet()
{
_logger.Trace("AfterPropertiesSet");
base.AfterPropertiesSet();
}
}
public class CountingAfterReturningAdvisor : StaticMethodMatcherPointcutAdvisor
{
private ITestObject testObject;
@@ -71,26 +116,62 @@ namespace Spring.Aop.Framework.AutoProxy
set { this.testObject = value; }
}
public int GetCalls()
{
return ((CountingAfterReturningAdvice) base.Advice).GetCalls();
}
public CountingAfterReturningAdvisor()
{
LogManager.GetLogger(this.GetType()).Trace("Created instance #" + this.GetHashCode());
base.Advice = new CountingAfterReturningAdvice();
}
public override bool Matches(MethodInfo method, Type targetType)
{
return true;
}
}
public class SomeOtherObject
{}
public class SomeOtherObject : ICloneable
{
public SomeOtherObject()
{
LogManager.GetLogger(this.GetType()).Trace("Created instance #" + this.GetHashCode());
}
public class IndependentObject
{ }
public object Clone()
{
return this;
}
}
public class IndependentObject : ICloneable
{
public IndependentObject()
{
LogManager.GetLogger(this.GetType()).Trace("Created instance #" + this.GetHashCode());
}
public object Clone()
{
return this;
}
}
public class TestObjectFactoryObject : IFactoryObject, IInitializingObject
{
private bool initialized = false;
private ITestObject testObject;
private SomeOtherObject someOtherObject;
private readonly ILog _logger;
public int GetObjectCounter = 0;
public TestObjectFactoryObject()
{
_logger = LogManager.GetLogger(this.GetType().Name + "#" + this.GetHashCode());
_logger.Trace("Created instance");
}
public SomeOtherObject SomeOtherObject
@@ -101,15 +182,15 @@ namespace Spring.Aop.Framework.AutoProxy
public object GetObject()
{
GetObjectCounter++;
// return product only, if factory has been fully initialized!
if (!initialized)
{
_logger.Trace("GetObject(): not initialized, returning null");
return null;
}
else
{
return testObject;
}
_logger.Trace("GetObject(): initialized, returning testObject");
return testObject;
}
public Type ObjectType
@@ -119,12 +200,11 @@ namespace Spring.Aop.Framework.AutoProxy
// return type only if we are ready to deliver our product!
if (!initialized)
{
_logger.Trace("get_ObjectType(): not initialized, returning null");
return null;
}
else
{
return typeof(ITestObject);
}
_logger.Trace("get_ObjectType(): initialized, returning typeof(ITestObject)");
return typeof(ITestObject);
}
}
@@ -135,6 +215,7 @@ namespace Spring.Aop.Framework.AutoProxy
public void AfterPropertiesSet()
{
_logger.Trace("AfterPropertiesSet");
Assert.IsNotNull(someOtherObject);
testObject = new TestObject();
initialized = true;

View File

@@ -2,22 +2,23 @@
<objects xmlns="http://www.springframework.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd"
default-autowire="byType"
default-autowire="no"
>
<description>
Reproduces a problem with AutoProxyCreators, IFactoryObjects,
circular dependencies and a certain order of object definitions
</description>
<!-- start instantiating a factoryobject -->
<!-- start instantiating a factoryobject -->
<object id="testObjectFactory" type="Spring.Aop.Framework.AutoProxy.TestObjectFactoryObject, Spring.Aop.Tests">
<property name="SomeOtherObject" ref="someOtherObject" />
</object>
<!-- note that testAdvisor is defined *after* 'testObjectFactory'! -->
<object id="testAdvisor" type="Spring.Aop.Framework.AutoProxy.TestAdvisor, Spring.Aop.Tests">
<property name="testObject" ref="testObjectFactory" /> <!-- ref on testObjectFactory closes the dep circle -->
</object>
<!-- note that testAdvisor is defined *after* 'testObjectFactory'! -->
<object id="testAdvisor" type="Spring.Aop.Framework.AutoProxy.CountingAfterReturningAdvisor, Spring.Aop.Tests">
<property name="testObject" ref="testObjectFactory" />
<!-- ref on testObjectFactory closes the dep circle -->
</object>
<!--
This object can be instantiated without any additional deps
@@ -30,6 +31,6 @@
<!-- match everything -->
<object id="aapc" type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator, Spring.Aop"/>
<object id="aapc" type="Spring.Aop.Framework.AutoProxy.TestDefaultAdvisorAutoProxyCreator, Spring.Aop.Tests" />
</objects>

View File

@@ -243,9 +243,10 @@ namespace Spring.Aop.Framework
}
/// <summary>
/// Must see effect immediately on behaviour.
/// Must see effect immediately on behaviour.
/// TODO (EE): Note that we can't add or remove interfaces without reconfiguring the singleton.
/// </summary>
[Test]
[Test, Ignore("change according to ProxyFactoryBeanTests.canAddAndRemoveAdvicesOnSingleton")]
public void CanAddAndRemoveIntroductionsOnSingleton()
{
try

View File

@@ -128,7 +128,12 @@ namespace Spring
#region IObjectFactory Members
public object this[string name]
public bool IsCaseSensitive
{
get { return true; }
}
public object this[string name]
{
get { return null; }
}
@@ -216,7 +221,13 @@ namespace Spring
#region IObjectFactory Members
public object this[string name]
public bool IsCaseSensitive
{
get { innerExecute();
return true; }
}
public object this[string name]
{
get
{

View File

@@ -263,6 +263,11 @@ namespace Spring.Context
// factory.AddObjectPostProcessor(new ApplicationContextAwareProcessor(this));
}
public override bool IsObjectNameInUse(string objectName)
{
return factory.IsObjectNameInUse(objectName);
}
public override IConfigurableListableObjectFactory ObjectFactory
{
get { return factory; }
@@ -416,7 +421,12 @@ namespace Spring.Context
#region IObjectFactory Members
public object this[string name]
public bool IsCaseSensitive
{
get { return true; }
}
public object this[string name]
{
get { return null; }
}

View File

@@ -158,7 +158,12 @@ namespace Spring.Context.Support
#region IObjectFactory Members
public object this[string name]
public bool IsCaseSensitive
{
get { return true; }
}
public object this[string name]
{
get { return null; }
}

View File

@@ -26,8 +26,10 @@ using System.Reflection;
using NUnit.Framework;
using Spring.Aop.Config;
using Spring.Aop.Framework.AutoProxy;
using Spring.Context;
using Spring.Context.Support;
using Spring.Core.IO;
using Spring.Objects;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
@@ -40,6 +42,31 @@ namespace Spring.Transaction.Config
[TestFixture]
public class TxNamespaceParserTests
{
private class ResourceXmlApplicationContext : AbstractXmlApplicationContext
{
private readonly IResource[] configurationResources;
public ResourceXmlApplicationContext(params IResource[] configurationResources)
: base()
{
this.configurationResources = configurationResources;
}
protected override void LoadObjectDefinitions(XmlObjectDefinitionReader objectDefinitionReader)
{
base.LoadObjectDefinitions(objectDefinitionReader);
objectDefinitionReader.LoadObjectDefinitions(configurationResources);
}
protected override string[] ConfigurationLocations
{
get { return null; }
}
}
private const string APPCTXCFG_PROLOG = @"<?xml version='1.0' encoding='utf-8' ?>";
private const string APPCTXCFG_START = APPCTXCFG_PROLOG + @"<objects xmlns='http://www.springframework.net' xmlns:tx='http://www.springframework.net/tx'>";
private const string APPCTXCFG_END = @"</objects>";
private IApplicationContext ctx;
[SetUp]
@@ -50,6 +77,19 @@ namespace Spring.Transaction.Config
ctx = new XmlApplicationContext("assembly://Spring.Data.Tests/Spring.Transaction.Config/TxNamespaceParserTests.xml");
}
[Test]
public void AppliesTxAttributeDrivenAttributes()
{
StringResource appCtxCfg = new StringResource(
APPCTXCFG_START
+ "<tx:attribute-driven transaction-manager='otherTxManager' proxy-target-type='true' order='2' />"
+ APPCTXCFG_END);
IApplicationContext appCtx = new ResourceXmlApplicationContext(appCtxCfg);
// DefaultAdvisorAutoProxyCreator daapc = (DefaultAdvisorAutoProxyCreator) appCtx.GetObject(AopNamespaceUtils.AUTO_PROXY_CREATOR_OBJECT_NAME);
// Assert.AreEqual(2, daapc.Order);
}
[Test]
public void Registered()
{

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net" xmlns:tx="http://www.springframework.net/tx">
<tx:attribute-driven transaction-manager='otherTxManager' proxy-target-type='true' order='2' />
</objects>

View File

@@ -25,9 +25,14 @@ namespace Spring.Messaging.Nms.Connections
{
public class TestMessageConsumer : IMessageConsumer
{
public event MessageListener Listener;
private void InvokeListener(IMessage message)
{
MessageListener listener = Listener;
if (listener != null) listener(message);
}
public IMessage Receive()
{
throw new NotImplementedException();

View File

@@ -46,10 +46,6 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
</Reference>
<Reference Include="Common.Logging.Log4Net, Version=1.2.0.2, Culture=neutral, PublicKeyToken=af08829b84f0328e, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.Log4Net.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\Net\2.0\log4net.dll</HintPath>

View File

@@ -32,12 +32,17 @@ limitations under the License.
<common>
<logging>
<!--
<factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
<arg key="level" value="INFO" />
<arg key="showLogName" value="true" />
<arg key="showDataTime" value="true" />
<arg key="dateTimeFormat" value="yyyy/MM/dd HH:mm:ss:fff" />
</factoryAdapter>
-->
<factoryAdapter type="Common.Logging.Simple.TraceLoggerFactoryAdapter, Common.Logging">
<arg key="level" value="INFO" />
</factoryAdapter>
</logging>
</common>

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{41BC3AEA-7EB3-48BF-B1EC-84119376AC98}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -33,10 +33,6 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
</Reference>
<Reference Include="Common.Logging.Log4Net, Version=1.2.0.2, Culture=neutral, PublicKeyToken=af08829b84f0328e, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.Log4Net.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\Net\2.0\log4net.dll</HintPath>