diff --git a/Spring.Net.2003.sln b/Spring.Net.2003.sln
index a58ecbe4..3354399d 100644
--- a/Spring.Net.2003.sln
+++ b/Spring.Net.2003.sln
@@ -211,12 +211,12 @@ Global
{E2689B4A-A951-420E-A274-BE5EBCD5F8D8}.Release-1.1.Build.0 = Release-1.1|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug.ActiveCfg = Debug|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug.Build.0 = Debug|.NET
- {2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug-1.1.ActiveCfg = Debug|.NET
- {2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug-1.1.Build.0 = Debug|.NET
+ {2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug-1.1.ActiveCfg = Debug-1.1|.NET
+ {2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug-1.1.Build.0 = Debug-1.1|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release.ActiveCfg = Release|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release.Build.0 = Release|.NET
- {2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release-1.1.ActiveCfg = Release|.NET
- {2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release-1.1.Build.0 = Release|.NET
+ {2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release-1.1.ActiveCfg = Release-1.1|.NET
+ {2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release-1.1.Build.0 = Release-1.1|.NET
{C17B27C2-4343-45BA-9A21-73C3CEC19BAD}.Debug.ActiveCfg = Debug|.NET
{C17B27C2-4343-45BA-9A21-73C3CEC19BAD}.Debug.Build.0 = Debug|.NET
{C17B27C2-4343-45BA-9A21-73C3CEC19BAD}.Debug-1.1.ActiveCfg = Debug|.NET
diff --git a/Spring.Net.2005.sln b/Spring.Net.2005.sln
index e6f4da04..28faa870 100644
--- a/Spring.Net.2005.sln
+++ b/Spring.Net.2005.sln
@@ -318,7 +318,6 @@ Global
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {130E1609-45A7-4F65-B112-105F2DD3E2CE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Release|.NET.ActiveCfg = Release|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Release|.NET.Build.0 = Release|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -330,7 +329,6 @@ Global
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {4A07E150-ED90-407C-8CAD-4760444DDFD9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|.NET.ActiveCfg = Release|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|.NET.Build.0 = Release|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -354,7 +352,6 @@ Global
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Release|.NET.ActiveCfg = Release|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Release|.NET.Build.0 = Release|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -397,7 +394,6 @@ Global
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {AEB1578C-9018-4D49-B440-789F38DD2F29}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Release|.NET.ActiveCfg = Release|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Release|Any CPU.Build.0 = Release|Any CPU
@@ -407,7 +403,6 @@ Global
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Release|.NET.ActiveCfg = Release|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Release|Any CPU.Build.0 = Release|Any CPU
diff --git a/src/Spring/Spring.Core/Collections/CaseInsensitiveHashtable.cs b/src/Spring/Spring.Core/Collections/CaseInsensitiveHashtable.cs
new file mode 100644
index 00000000..e838b3a8
--- /dev/null
+++ b/src/Spring/Spring.Core/Collections/CaseInsensitiveHashtable.cs
@@ -0,0 +1,87 @@
+using System.Collections;
+using System.Globalization;
+using Spring.Util;
+
+namespace Spring.Collections
+{
+ ///
+ /// Provides a performance improved hashtable with case-insensitive (string-only! based) key handling.
+ ///
+ /// Erich Eichinger
+ public class CaseInsensitiveHashtable : Hashtable
+ {
+ private readonly TextInfo _textInfo;
+ private readonly CompareInfo _compareInfo;
+
+ ///
+ /// Creates a case-insensitive hashtable using .
+ ///
+ public CaseInsensitiveHashtable()
+ : this(null, CultureInfo.CurrentCulture)
+ {}
+
+ ///
+ /// Creates a case-insensitive hashtable using the given .
+ ///
+ /// the to calculate the hashcode
+ public CaseInsensitiveHashtable(CultureInfo culture)
+ : this(null, culture)
+ {}
+
+ ///
+ /// Creates a case-insensitive hashtable using the given , initially
+ /// populated with entries from another dictionary.
+ ///
+ /// the dictionary to copy entries from
+ /// the to calculate the hashcode
+ public CaseInsensitiveHashtable(IDictionary d, CultureInfo culture)
+ :this(d, culture.TextInfo, culture.CompareInfo)
+ {}
+
+ ///
+ /// Creates a case-insensitive hashtable using the given , initially
+ /// populated with entries from another dictionary.
+ ///
+ protected CaseInsensitiveHashtable(IDictionary d, TextInfo textInfo, CompareInfo compareInfo)
+ {
+ AssertUtils.ArgumentNotNull(textInfo, "textInfo");
+ _textInfo = textInfo;
+ _compareInfo = compareInfo;
+
+ if (d != null)
+ {
+ IDictionaryEnumerator enumerator = d.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ this.Add(enumerator.Key, enumerator.Value);
+ }
+ }
+ }
+
+ ///
+ /// Calculate the hashcode of the given string key, using the configured culture.
+ ///
+ ///
+ ///
+ protected override int GetHash(object key)
+ {
+ return _textInfo.ToLower((string) key).GetHashCode();
+ }
+
+ ///
+ /// Compares two keys
+ ///
+ protected override bool KeyEquals(object item, object key)
+ {
+ return 0==_compareInfo.Compare((string) item, (string) key, CompareOptions.IgnoreCase);
+ }
+
+ ///
+ /// Creates a shallow copy of the current instance.
+ ///
+ public override object Clone()
+ {
+ return new CaseInsensitiveHashtable(this, _textInfo, _compareInfo );
+ }
+ }
+}
diff --git a/src/Spring/Spring.Core/Collections/SynchronizedHashtable.cs b/src/Spring/Spring.Core/Collections/SynchronizedHashtable.cs
index c8ba2cc8..50e483c2 100644
--- a/src/Spring/Spring.Core/Collections/SynchronizedHashtable.cs
+++ b/src/Spring/Spring.Core/Collections/SynchronizedHashtable.cs
@@ -1,366 +1,397 @@
-#region License
-
-/*
- * Copyright 2002-2004 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
-
-using System;
-using System.Collections;
-using Spring.Util;
-
-namespace Spring.Collections
-{
- ///
- /// Synchronized that, unlike hashtable created
- /// using method, synchronizes
- /// reads from the underlying hashtable in addition to writes.
- ///
- ///
- ///
- /// In addition to synchronizing reads, this implementation also fixes
- /// IEnumerator/ICollection issue described at
- /// http://msdn.microsoft.com/en-us/netframework/aa570326.aspx
- /// (search for SynchronizedHashtable for issue description), by implementing
- /// interface explicitly, and returns thread safe enumerator
- /// implementations as well.
- ///
- ///
- /// This class should be used whenever a truly synchronized
- /// is needed.
- ///
- ///
- /// Aleksandar Seovic
- [Serializable]
- public class SynchronizedHashtable : IDictionary, ICollection, IEnumerable, ICloneable
- {
- private readonly Hashtable _table;
-
- #region Constructors
-
- ///
- /// Initializes a new instance of
- ///
- public SynchronizedHashtable()
- {
- this._table = new Hashtable();
- }
-
- ///
- /// Initializes a new instance of , copying inital entries from .
- ///
- public SynchronizedHashtable(IDictionary dictionary)
- {
- AssertUtils.ArgumentNotNull(dictionary, "dictionary");
- this._table = new Hashtable(dictionary);
- }
-
- #endregion
-
- #region Properties
-
- ///
- ///Gets a value indicating whether the object is read-only.
- ///
- ///
- ///true if the object is read-only; otherwise, false.
- ///
- public bool IsReadOnly
- {
- get
- {
- lock (SyncRoot)
- {
- return _table.IsReadOnly;
- }
- }
- }
-
- ///
- ///Gets a value indicating whether the object has a fixed size.
- ///
- ///
- ///true if the object has a fixed size; otherwise, false.
- ///
- public bool IsFixedSize
- {
- get
- {
- lock (SyncRoot)
- {
- return _table.IsFixedSize;
- }
- }
- }
-
- ///
- ///Gets a value indicating whether access to the is synchronized (thread safe).
- ///
- ///
- ///true if access to the is synchronized (thread safe); otherwise, false.
- ///
- public bool IsSynchronized
- {
- get { return true; }
- }
-
- ///
- ///Gets an object containing the keys of the object.
- ///
- ///
- ///An object containing the keys of the object.
- ///
- public ICollection Keys
- {
- get
- {
- lock (SyncRoot)
- {
- return _table.Keys;
- }
- }
- }
-
- ///
- ///Gets an object containing the values in the object.
- ///
- ///
- ///An object containing the values in the object.
- ///
- public ICollection Values
- {
- get
- {
- lock (SyncRoot)
- {
- return _table.Values;
- }
- }
- }
-
- ///
- ///Gets an object that can be used to synchronize access to the .
- ///
- ///
- ///An object that can be used to synchronize access to the .
- ///
- public object SyncRoot
- {
- get { return _table.SyncRoot; }
- }
-
- ///
- ///Gets the number of elements contained in the .
- ///
- ///
- ///The number of elements contained in the .
- ///
- public int Count
- {
- get
- {
- lock (SyncRoot)
- {
- return _table.Count;
- }
- }
- }
-
- #endregion
-
- #region Methods
-
- ///
- ///Adds an element with the provided key and value to the object.
- ///
- ///The to use as the value of the element to add.
- ///The to use as the key of the element to add.
- ///An element with the same key already exists in the object.
- ///key is null.
- ///The is read-only.-or- The has a fixed size. 2
- public void Add(object key, object value)
- {
- lock (SyncRoot)
- {
- _table.Add(key, value);
- }
- }
-
- ///
- ///Removes all elements from the object.
- ///
- ///The object is read-only. 2
- public void Clear()
- {
- lock (SyncRoot)
- {
- _table.Clear();
- }
- }
-
- ///
- ///Creates a new object that is a copy of the current instance.
- ///
- ///
- ///A new object that is a copy of this instance.
- ///
- public object Clone()
- {
- lock (SyncRoot)
- {
- return new SynchronizedHashtable(this);
- }
- }
-
- ///
- ///Determines whether the object contains an element with the specified key.
- ///
- ///
- ///true if the contains an element with the key; otherwise, false.
- ///
- ///The key to locate in the object.
- ///key is null. 2
- public bool Contains(object key)
- {
- lock (SyncRoot)
- {
- return _table.Contains(key);
- }
- }
-
- ///
- /// Returns, whether this contains an entry with the specified .
- ///
- ///The key to look for
- ///, if this contains an entry with this
- public bool ContainsKey(object key)
- {
- lock (SyncRoot)
- {
- return _table.ContainsKey(key);
- }
- }
-
- ///
- /// Returns, whether this contains an entry with the specified .
- ///
- ///The valúe to look for
- ///, if this contains an entry with this
- public bool ContainsValue(object value)
- {
- lock (SyncRoot)
- {
- return _table.ContainsValue(value);
- }
- }
-
- ///
- ///Copies the elements of the to an , starting at a particular index.
- ///
- ///The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing.
- ///The zero-based index in array at which copying begins.
- ///array is null.
- ///The type of the source cannot be cast automatically to the type of the destination array.
- ///index is less than zero.
- ///array is multidimensional.-or- index is equal to or greater than the length of array.-or- The number of elements in the source is greater than the available space from index to the end of the destination array. 2
- public void CopyTo(Array array, int index)
- {
- lock (SyncRoot)
- {
- _table.CopyTo(array, index);
- }
- }
-
- ///
- ///Returns an object for the object.
- ///
- ///
- ///An object for the object.
- ///
- public IDictionaryEnumerator GetEnumerator()
- {
- lock (SyncRoot)
- {
- return new SynchronizedDictionaryEnumerator(SyncRoot, _table.GetEnumerator());
- }
- }
-
- ///
- ///Removes the element with the specified key from the object.
- ///
- ///The key of the element to remove.
- ///The object is read-only.-or- The has a fixed size.
- ///key is null. 2
- public void Remove(object key)
- {
- lock (SyncRoot)
- {
- _table.Remove(key);
- }
- }
-
- #endregion
-
- #region IEnumerable implementation
-
- ///
- ///Returns an enumerator that iterates through a collection.
- ///
- ///
- ///An object that can be used to iterate through the collection.
- ///
- IEnumerator IEnumerable.GetEnumerator()
- {
- lock (SyncRoot)
- {
- return new SynchronizedEnumerator(SyncRoot, ((IEnumerable) _table).GetEnumerator());
- }
- }
-
- #endregion
-
- #region Indexer
-
- ///
- ///Gets or sets the element with the specified key.
- ///
- ///
- ///The element with the specified key.
- ///
- ///The key of the element to get or set.
- ///The property is set and the object is read-only.-or- The property is set, key does not exist in the collection, and the has a fixed size.
- ///key is null. 2
- public object this[object key]
- {
- get
- {
- lock (SyncRoot)
- {
- return _table[key];
- }
- }
- set
- {
- lock (SyncRoot)
- {
- _table[key] = value;
- }
- }
- }
-
- #endregion
- }
+#region License
+
+/*
+ * Copyright 2002-2004 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
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using Spring.Util;
+
+namespace Spring.Collections
+{
+ ///
+ /// Synchronized that, unlike hashtable created
+ /// using method, synchronizes
+ /// reads from the underlying hashtable in addition to writes.
+ ///
+ ///
+ ///
+ /// In addition to synchronizing reads, this implementation also fixes
+ /// IEnumerator/ICollection issue described at
+ /// http://msdn.microsoft.com/en-us/netframework/aa570326.aspx
+ /// (search for SynchronizedHashtable for issue description), by implementing
+ /// interface explicitly, and returns thread safe enumerator
+ /// implementations as well.
+ ///
+ ///
+ /// This class should be used whenever a truly synchronized
+ /// is needed.
+ ///
- /// This class provides singleton / prototype determination, singleton caching,
- /// object definition aliasing,
- /// handling, and object definition merging for child object definitions.
- ///
- ///
- /// Rod Johnson
- /// Juergen Hoeller
- /// Rick Evans (.NET)
- [Serializable]
- public abstract class AbstractObjectFactory : IConfigurableObjectFactory
- {
- ///
- /// Marker object to be temporarily registered in the singleton cache,
- /// while instantiating an object (in order to be able to detect circular references).
- ///
- private static readonly object CURRENTLY_IN_CREATION = new Object();
-
- ///
- /// The instance for this class.
- ///
- private readonly ILog log = LogManager.GetLogger(typeof(AbstractObjectFactory));
-
- ///
- /// 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.
- ///
- private static object emptyObject = new object();
-
-
-
- #region Constructor (s) / Destructor
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- ///
- ///
- /// This constructor implicitly creates an
- ///
- /// that treats the names of objects in this factory in a case-sensitive fashion.
- ///
- ///
- /// This is an class, and as such exposes no public constructors.
- ///
- ///
- protected AbstractObjectFactory() : this(true)
- {}
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- ///
- ///
- /// This is an class, and as such exposes no public constructors.
- ///
- ///
- ///
- /// if the names of objects in this factory are to be treated in a
- /// case-sensitive fashion.
- ///
- protected AbstractObjectFactory(bool caseSensitive)
- {
- this.log = LogManager.GetLogger(this.GetType());
- if (caseSensitive)
- {
- this.aliasMap = new SynchronizedHashtable();
- this.singletonCache = new Hashtable();
- this.singletonsInCreation = new Hashtable();
- }
- else
- {
- this.aliasMap = new SynchronizedHashtable(CollectionsUtil.CreateCaseInsensitiveHashtable());
- this.singletonCache = CollectionsUtil.CreateCaseInsensitiveHashtable();
- this.singletonsInCreation = CollectionsUtil.CreateCaseInsensitiveHashtable();
- }
- }
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- ///
- ///
- /// This is an class, and as such exposes no public constructors.
- ///
- ///
- ///
- /// if the names of objects in this factory are to be treated in a
- /// case-sensitive fashion.
- ///
- ///
- /// Any parent object factory; may be .
- ///
- protected AbstractObjectFactory(bool caseSensitive, IObjectFactory parentFactory) : this(caseSensitive)
- {
- ParentObjectFactory = parentFactory;
- }
-
- #endregion
-
- #region Properties
-
- ///
- /// Gets the of
- /// s
- /// that will be applied to objects created by this factory.
- ///
- public IList ObjectPostProcessors
- {
- get { return objectPostProcessors; }
- }
-
- ///
- /// Gets the set of classes that will be ignored for autowiring.
- ///
- ///
- ///
- /// The elements of this are
- /// s.
- ///
- ///
- public ISet IgnoredDependencyTypes
- {
- get { return ignoreDependencyTypes; }
- }
-
- ///
- /// Returns, whether this object factory instance contains objects.
- ///
- protected bool HasInstantiationAwareBeanPostProcessors
- {
- get { return hasInstantiationAwareBeanPostProcessors; }
- }
-
- ///
- /// Returns, whether this object factory instance contains objects.
- ///
- protected bool HasDestructionAwareBeanPostProcessors
- {
- get { return hasDestructionAwareBeanPostProcessors; }
- }
-
- #endregion
-
- #region Methods
-
- ///
- /// Return an instance (possibly shared or independent) of the given object name.
- ///
- /// The name of the object to return.
- ///
- /// The the object may match. Can be an interface or
- /// superclass of the actual class. For example, if the value is the
- /// class, this method will succeed whatever the
- /// class of the returned instance.
- ///
- ///
- /// The arguments to use if creating a prototype using explicit arguments to
- /// a factory method. If there is no factory method and the
- /// supplied array is not , then
- /// match the argument values by type and call the object's constructor.
- ///
- /// The instance of the object.
- ///
- /// If there's no such object definition.
- ///
- ///
- /// If the object could not be created.
- ///
- ///
- /// If the object is not of the required type.
- ///
- ///
- /// If the supplied is .
- ///
- ///
- public object GetObject(string name, Type requiredType, object[] arguments)
- {
- string objectName = TransformedObjectName(name);
- object instance = null;
- // eagerly check singleton cache for manually registered singletons...
- object sharedInstance = GetSingleton(objectName);
-
- if (sharedInstance != null)
- {
- #region Instrumentation
-
- if (IsSingletonCurrentlyInCreation(objectName))
+ */
+
+#endregion
+
+#region Imports
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.ComponentModel;
+
+using Common.Logging;
+
+using Spring.Collections;
+using Spring.Core;
+using Spring.Core.TypeConversion;
+using Spring.Objects.Factory.Config;
+using Spring.Util;
+
+#endregion
+
+namespace Spring.Objects.Factory.Support
+{
+ ///
+ /// Abstract superclass for
+ /// implementations.
+ ///
+ ///
+ ///
+ /// This class provides singleton / prototype determination, singleton caching,
+ /// object definition aliasing,
+ /// handling, and object definition merging for child object definitions.
+ ///
+ ///
+ /// Rod Johnson
+ /// Juergen Hoeller
+ /// Rick Evans (.NET)
+ [Serializable]
+ public abstract class AbstractObjectFactory : IConfigurableObjectFactory
+ {
+ ///
+ /// Marker object to be temporarily registered in the singleton cache,
+ /// while instantiating an object (in order to be able to detect circular references).
+ ///
+ private static readonly object CURRENTLY_IN_CREATION = new Object();
+
+ ///
+ /// The instance for this class.
+ ///
+ private readonly ILog log = LogManager.GetLogger(typeof(AbstractObjectFactory));
+
+ ///
+ /// 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.
+ ///
+ private static object emptyObject = new object();
+
+
+
+ #region Constructor (s) / Destructor
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ ///
+ ///
+ /// This constructor implicitly creates an
+ ///
+ /// that treats the names of objects in this factory in a case-sensitive fashion.
+ ///
+ ///
+ /// This is an class, and as such exposes no public constructors.
+ ///
+ ///
+ protected AbstractObjectFactory()
+ : this(true)
+ { }
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ ///
+ ///
+ /// This is an class, and as such exposes no public constructors.
+ ///
+ ///
+ ///
+ /// if the names of objects in this factory are to be treated in a
+ /// case-sensitive fashion.
+ ///
+ protected AbstractObjectFactory(bool caseSensitive)
+ {
+ this.log = LogManager.GetLogger(this.GetType());
+ this.caseSensitive = caseSensitive;
+ if (caseSensitive)
+ {
+ this.aliasMap = new Hashtable();
+ this.singletonCache = new Hashtable();
+ this.singletonsInCreation = new Hashtable();
+ }
+ else
+ {
+ this.aliasMap = new CaseInsensitiveHashtable();
+ this.singletonCache = new CaseInsensitiveHashtable();
+ this.singletonsInCreation = new CaseInsensitiveHashtable();
+ }
+ }
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ ///
+ ///
+ /// This is an class, and as such exposes no public constructors.
+ ///
+ ///
+ ///
+ /// if the names of objects in this factory are to be treated in a
+ /// case-sensitive fashion.
+ ///
+ ///
+ /// Any parent object factory; may be .
+ ///
+ protected AbstractObjectFactory(bool caseSensitive, IObjectFactory parentFactory)
+ : this(caseSensitive)
+ {
+ ParentObjectFactory = parentFactory;
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Returns, whether this factory treats object names case sensitive or not.
+ ///
+ public bool IsCaseSensitive
+ {
+ get { return caseSensitive; }
+ }
+
+ ///
+ /// Gets the of
+ /// s
+ /// that will be applied to objects created by this factory.
+ ///
+ public IList ObjectPostProcessors
+ {
+ get { return objectPostProcessors; }
+ }
+
+ ///
+ /// Gets the set of classes that will be ignored for autowiring.
+ ///
+ ///
+ ///
+ /// The elements of this are
+ /// s.
+ ///
+ ///
+ public ISet IgnoredDependencyTypes
+ {
+ get { return ignoreDependencyTypes; }
+ }
+
+ ///
+ /// Returns, whether this object factory instance contains objects.
+ ///
+ protected bool HasInstantiationAwareBeanPostProcessors
+ {
+ get { return hasInstantiationAwareBeanPostProcessors; }
+ }
+
+ ///
+ /// Returns, whether this object factory instance contains objects.
+ ///
+ protected bool HasDestructionAwareBeanPostProcessors
+ {
+ get { return hasDestructionAwareBeanPostProcessors; }
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Return an instance (possibly shared or independent) of the given object name.
+ ///
+ /// The name of the object to return.
+ ///
+ /// The the object may match. Can be an interface or
+ /// superclass of the actual class. For example, if the value is the
+ /// class, this method will succeed whatever the
+ /// class of the returned instance.
+ ///
+ ///
+ /// The arguments to use if creating a prototype using explicit arguments to
+ /// a factory method. If there is no factory method and the
+ /// supplied array is not , then
+ /// match the argument values by type and call the object's constructor.
+ ///
+ /// The instance of the object.
+ ///
+ /// If there's no such object definition.
+ ///
+ ///
+ /// If the object could not be created.
+ ///
+ ///
+ /// If the object is not of the required type.
+ ///
+ ///
+ /// If the supplied is .
+ ///
+ ///
+ public object GetObject(string name, Type requiredType, object[] arguments)
+ {
+ string objectName = TransformedObjectName(name);
+ object instance = null;
+ // eagerly check singleton cache for manually registered singletons...
+ object sharedInstance = GetSingleton(objectName);
+
+ if (sharedInstance != null)
+ {
+ #region Instrumentation
+
+ if (IsSingletonCurrentlyInCreation(objectName))
+ {
+ if (log.IsDebugEnabled)
+ {
+ log.Debug("Returning eagerly cached instance of singleton object '" + objectName +
+ "' that is not fully initialized yet - a consequence of a circular reference");
+ }
+ }
+ else
+ {
+ if (log.IsDebugEnabled)
+ {
+ log.Debug(string.Format("Returning cached instance of singleton object '{0}'.", objectName));
+ }
+ }
+
+ #endregion
+
+ instance = GetObjectForInstance(name, sharedInstance);
+ }
+ else
+ {
+ // check if object definition exists
+ RootObjectDefinition mergedObjectDefinition = null;
+ mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
+ if (mergedObjectDefinition == null)
+ {
+ if (ParentObjectFactory != null)
+ {
+ return ParentObjectFactory.GetObject(name, requiredType, arguments);
+ }
+ throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
+ }
+
+ CheckMergedObjectDefinition(mergedObjectDefinition, objectName, requiredType, arguments);
+
+ // return IObjectDefinition instance itself for an abstract object-definition
+ if (mergedObjectDefinition.IsAbstract)
+ {
+ instance = mergedObjectDefinition;
+ }
+ else if (mergedObjectDefinition.IsSingleton)
+ {
+ // create object instance...
+ sharedInstance = CreateAndCacheSingletonInstance(objectName, mergedObjectDefinition, arguments);
+ instance = GetObjectForInstance(name, sharedInstance);
+ }
+ else
+ {
+ // it's a prototype, so create a new instance...
+ instance = CreateObject(name, mergedObjectDefinition, arguments);
+ }
+ }
+ // check that any required type matches the type of the actual object instance...
+ if (requiredType != null && !requiredType.IsAssignableFrom(instance.GetType()))
+ {
+ throw new ObjectNotOfRequiredTypeException(name, requiredType, instance);
+ }
+ return instance;
+ }
+
+
+
+ ///
+ /// Apply the property values of the object definition with the supplied
+ /// to the supplied .
+ ///
+ ///
+ ///
+ /// The object definition can either define a fully self-contained object,
+ /// reusing it's property values, or just property values meant to be used
+ /// for existing object instances.
+ ///
+ ///
+ ///
+ /// The existing object that the property values for the named object will
+ /// be applied to.
+ ///
+ ///
+ /// The name of the object definition associated with the property values that are
+ /// to be applied.
+ ///
+ ///
+ /// In case of errors.
+ ///
+ public virtual void ApplyObjectPropertyValues(object instance, string name)
+ {
+ // explicit no-op...
+ }
+
+ ///
+ /// Initializes the given with the
+ /// custom s registered with
+ /// this factory.
+ ///
+ ///
+ /// The to initialise.
+ ///
+ protected void InitObjectWrapper(IObjectWrapper wrapper)
+ {
+ }
+
+ ///
+ /// Create an object instance for the given object definition.
+ ///
+ ///
+ ///
+ /// The object definition will already have been merged with the parent
+ /// definition in case of a child definition.
+ ///
+ ///
+ /// All the other methods in this class invoke this method, although objects
+ /// may be cached after being instantiated by this method. All object
+ /// instantiation within this class is performed by this method.
+ ///
+ ///
+ /// The name of the object.
+ ///
+ /// The object definition for the object that is to be instantiated.
+ ///
+ ///
+ /// The arguments to use if creating a prototype using explicit arguments to
+ /// a factory method. If there is no factory method and the
+ /// supplied array is not ,
+ /// then match the argument values by type and call the object's constructor.
+ ///
+ ///
+ /// A new instance of the object.
+ ///
+ ///
+ /// In case of errors.
+ ///
+ protected abstract object CreateObject(string name, RootObjectDefinition definition, object[] arguments);
+
+ ///
+ /// Destroy the target object.
+ ///
+ ///
+ ///
+ /// Must destroy objects that depend on the given object before the object itself,
+ /// nor throw an exception.
+ ///
+ ///
+ ///
+ /// The name of the object.
+ ///
+ ///
+ /// The target object instance to destroyed.
+ ///
+ protected abstract void DestroyObject(string name, object target);
+
+ ///
+ /// Does this object factory contain an object definition with the
+ /// supplied ?
+ ///
+ ///
+ ///
+ /// Does not consider any hierarchy this factory may participate in.
+ /// Invoked by
+ ///
+ /// when no cached singleton instance is found.
+ ///
+ ///
+ ///
+ /// The name of the object to look for.
+ ///
+ ///
+ /// if this object factory contains an object
+ /// definition with the supplied .
+ ///
+ public abstract bool ContainsObjectDefinition(string name);
+
+ ///
+ /// Adds the supplied (object) to this factory's
+ /// singleton cache.
+ ///
+ ///
+ ///
+ /// To be called for eager registration of singletons, e.g. to be able to
+ /// resolve circular references.
+ ///
+ ///
+ /// If a singleton has already been registered under the same name as
+ /// the supplied , then the old singleton will
+ /// be replaced.
+ ///
+ ///
+ /// The name of the object.
+ /// The singleton object.
+ ///
+ /// If the argument is
+ /// or consists wholly of whitespace characters; or if the
+ /// is .
+ ///
+ protected virtual void AddSingleton(string name, object singleton)
+ {
+ AssertUtils.ArgumentHasText(name, "The object name must not be empty.");
+ AssertUtils.ArgumentNotNull(singleton, "singleton");
+ lock (singletonCache)
+ {
+ singletonCache[name] = singleton;
+ }
+ }
+
+ ///
+ /// Return the object name, stripping out the factory dereference prefix if
+ /// necessary, and resolving aliases to canonical names.
+ ///
+ ///
+ /// The transformed name of the object.
+ ///
+ protected string TransformedObjectName(string name)
+ {
+ string objectName = ObjectFactoryUtils.TransformedObjectName(name);
+ // handle aliasing...
+ lock (aliasMap)
+ {
+ string canonicalName = (string)aliasMap[objectName];
+ return canonicalName != null ? canonicalName : objectName;
+ }
+ }
+
+ ///
+ /// Ensures, that the given name is prefixed with
+ /// if it incidentially already starts with this prefix. This avoids troubles when dereferencing
+ /// the object name during
+ ///
+ protected string OriginalObjectName(string name)
+ {
+ string objectName = TransformedObjectName(name);
+ if (name.StartsWith(ObjectFactoryUtils.FactoryObjectPrefix))
+ {
+ objectName = ObjectFactoryUtils.FactoryObjectPrefix + objectName;
+ }
+ return objectName;
+ }
+
+ ///
+ /// Determines whether the specified name is defined as an alias as opposed
+ /// to the name of an actual object definition.
+ ///
+ /// The object name to check.
+ ///
+ /// true if the specified name is alias; otherwise, false.
+ ///
+ protected bool IsAlias(string name)
+ {
+ lock (aliasMap)
+ {
+ return aliasMap.Contains(name);
+ }
+ }
+
+ ///
+ /// Return a ,
+ /// even by traversing parent if the parameter is a child definition.
+ ///
+ ///
+ /// The name of the object.
+ ///
+ ///
+ /// Are ancestors to be included in the merge?
+ ///
+ ///
+ ///
+ /// Will ask the parent object factory if not found in this instance.
+ ///
+ ///
+ ///
+ /// A merged
+ /// with overridden properties.
+ ///
+ public virtual RootObjectDefinition GetMergedObjectDefinition(string name, bool includingAncestors)
+ {
+ return GetMergedObjectDefinition(name, GetObjectDefinition(name, includingAncestors));
+ }
+
+ ///
+ /// Return a ,
+ /// even by traversing parent if the parameter is a child definition.
+ ///
+ ///
+ /// A merged
+ /// with overridden properties.
+ ///
+ protected virtual RootObjectDefinition GetMergedObjectDefinition(string name, IObjectDefinition definition)
+ {
+ if (definition == null)
+ {
+ return null;
+ }
+ else if (definition is RootObjectDefinition)
+ {
+ return (RootObjectDefinition)definition;
+ }
+ else if (definition is ChildObjectDefinition)
+ {
+ ChildObjectDefinition childDefinition = (ChildObjectDefinition)definition;
+ RootObjectDefinition parentDefinition = null;
+ if (!name.Equals(childDefinition.ParentName))
+ {
+ parentDefinition =
+ GetMergedObjectDefinition(TransformedObjectName(childDefinition.ParentName), true);
+ }
+ else
+ {
+ if (ParentObjectFactory is AbstractObjectFactory)
+ {
+ parentDefinition =
+ ((AbstractObjectFactory)ParentObjectFactory).GetMergedObjectDefinition(
+ childDefinition.ParentName, true);
+ }
+ }
+ if (parentDefinition == null)
+ {
+ throw new NoSuchObjectDefinitionException(childDefinition.ParentName,
+ string.Format(
+ "Parent name '{0}' is equal to object name '{1}' - "
+ +
+ "cannot be resolved without an AbstractObjectFactory parent.",
+ childDefinition.ParentName, name));
+ }
+
+ RootObjectDefinition rootDefinition = CreateRootObjectDefinition(parentDefinition);
+ rootDefinition.OverrideFrom(childDefinition);
+ return rootDefinition;
+ }
+ else
+ {
+ throw new ObjectDefinitionStoreException(definition.ResourceDescription, name,
+ "Definition is neither a RootObjectDefinition nor a ChildObjectDefinition.");
+ }
+ }
+ /*
+ ///
+ /// Merges the object definitions.
+ ///
+ /// Object definition name.
+ /// The parent definition.
+ /// The child definition.
+ /// Merged object definition.
+ protected virtual RootObjectDefinition MergeObjectDefinitions(string name, IObjectDefinition parentDefinition,
+ IObjectDefinition childDefinition)
{
- if (log.IsDebugEnabled)
- {
- log.Debug("Returning eagerly cached instance of singleton object '" + objectName +
- "' that is not fully initialized yet - a consequence of a circular reference");
- }
+ RootObjectDefinition rootDefinition = CreateRootObjectDefinition(parentDefinition);
+ rootDefinition.OverrideFrom(childDefinition);
+ return rootDefinition;
}
- else
- {
- if (log.IsDebugEnabled)
- {
- log.Debug(string.Format("Returning cached instance of singleton object '{0}'.", objectName));
- }
- }
-
- #endregion
-
- instance = GetObjectForInstance(name, sharedInstance);
- }
- else
- {
- // check if object definition exists
- RootObjectDefinition mergedObjectDefinition = null;
- mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
- if (mergedObjectDefinition == null)
- {
- if (ParentObjectFactory != null)
- {
- return ParentObjectFactory.GetObject(name, requiredType, arguments);
- }
- throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
- }
-
- CheckMergedObjectDefinition(mergedObjectDefinition, objectName, requiredType, arguments);
-
- // return IObjectDefinition instance itself for an abstract object-definition
- if (mergedObjectDefinition.IsAbstract)
- {
- instance = mergedObjectDefinition;
- }
- else if (mergedObjectDefinition.IsSingleton)
- {
- // create object instance...
- sharedInstance = CreateAndCacheSingletonInstance(objectName, mergedObjectDefinition, arguments);
- instance = GetObjectForInstance(name, sharedInstance);
- }
- else
- {
- // it's a prototype, so create a new instance...
- instance = CreateObject(name, mergedObjectDefinition, arguments);
- }
- }
- // check that any required type matches the type of the actual object instance...
- if (requiredType != null && !requiredType.IsAssignableFrom(instance.GetType()))
- {
- throw new ObjectNotOfRequiredTypeException(name, requiredType, instance);
- }
- return instance;
- }
-
-
-
- ///
- /// Apply the property values of the object definition with the supplied
- /// to the supplied .
- ///
- ///
- ///
- /// The object definition can either define a fully self-contained object,
- /// reusing it's property values, or just property values meant to be used
- /// for existing object instances.
- ///
- ///
- ///
- /// The existing object that the property values for the named object will
- /// be applied to.
- ///
- ///
- /// The name of the object definition associated with the property values that are
- /// to be applied.
- ///
- ///
- /// In case of errors.
- ///
- public virtual void ApplyObjectPropertyValues(object instance, string name)
- {
- // explicit no-op...
- }
-
- ///
- /// Initializes the given with the
- /// custom s registered with
- /// this factory.
- ///
- ///
- /// The to initialise.
- ///
- protected void InitObjectWrapper(IObjectWrapper wrapper)
- {
- }
-
- ///
- /// Create an object instance for the given object definition.
- ///
- ///
- ///
- /// The object definition will already have been merged with the parent
- /// definition in case of a child definition.
- ///
- ///
- /// All the other methods in this class invoke this method, although objects
- /// may be cached after being instantiated by this method. All object
- /// instantiation within this class is performed by this method.
- ///
- ///
- /// The name of the object.
- ///
- /// The object definition for the object that is to be instantiated.
- ///
- ///
- /// The arguments to use if creating a prototype using explicit arguments to
- /// a factory method. If there is no factory method and the
- /// supplied array is not ,
- /// then match the argument values by type and call the object's constructor.
- ///
- ///
- /// A new instance of the object.
- ///
- ///
- /// In case of errors.
- ///
- protected abstract object CreateObject(string name, RootObjectDefinition definition, object[] arguments);
-
- ///
- /// Destroy the target object.
- ///
- ///
- ///
- /// Must destroy objects that depend on the given object before the object itself,
- /// nor throw an exception.
- ///
- ///
- ///
- /// The name of the object.
- ///
- ///
- /// The target object instance to destroyed.
- ///
- protected abstract void DestroyObject(string name, object target);
-
- ///
- /// Does this object factory contain an object definition with the
- /// supplied ?
- ///
- ///
- ///
- /// Does not consider any hierarchy this factory may participate in.
- /// Invoked by
- ///
- /// when no cached singleton instance is found.
- ///
- ///
- ///
- /// The name of the object to look for.
- ///
- ///
- /// if this object factory contains an object
- /// definition with the supplied .
- ///
- public abstract bool ContainsObjectDefinition(string name);
-
- ///
- /// Adds the supplied (object) to this factory's
- /// singleton cache.
- ///
- ///
- ///
- /// To be called for eager registration of singletons, e.g. to be able to
- /// resolve circular references.
- ///
- ///
- /// If a singleton has already been registered under the same name as
- /// the supplied , then the old singleton will
- /// be replaced.
- ///
- ///
- /// The name of the object.
- /// The singleton object.
- ///
- /// If the argument is
- /// or consists wholly of whitespace characters; or if the
- /// is .
- ///
- protected virtual void AddSingleton(string name, object singleton)
- {
- AssertUtils.ArgumentHasText(name, "The object name must not be empty.");
- AssertUtils.ArgumentNotNull(singleton, "singleton");
- lock (singletonCache)
- {
- singletonCache[name] = singleton;
- }
- }
-
- ///
- /// Return the object name, stripping out the factory dereference prefix if
- /// necessary, and resolving aliases to canonical names.
- ///
- ///
- /// The transformed name of the object.
- ///
- protected string TransformedObjectName(string name)
- {
- string objectName = ObjectFactoryUtils.TransformedObjectName(name);
- // handle aliasing...
- lock (aliasMap)
- {
- string canonicalName = (string) aliasMap[objectName];
- return canonicalName != null ? canonicalName : objectName;
- }
- }
-
- ///
- /// Ensures, that the given name is prefixed with
- /// if it incidentially already starts with this prefix. This avoids troubles when dereferencing
- /// the object name during
- ///
- protected string OriginalObjectName(string name)
- {
- string objectName = TransformedObjectName(name);
- if (name.StartsWith(ObjectFactoryUtils.FactoryObjectPrefix))
- {
- objectName = ObjectFactoryUtils.FactoryObjectPrefix + objectName;
- }
- return objectName;
- }
-
- ///
- /// Determines whether the specified name is defined as an alias as opposed
- /// to the name of an actual object definition.
- ///
- /// The object name to check.
- ///
- /// true if the specified name is alias; otherwise, false.
- ///
- protected bool IsAlias(string name)
- {
- lock (aliasMap)
- {
- return aliasMap.Contains(name);
- }
- }
-
- ///
- /// Return a ,
- /// even by traversing parent if the parameter is a child definition.
- ///
- ///
- /// The name of the object.
- ///
- ///
- /// Are ancestors to be included in the merge?
- ///
- ///
- ///
- /// Will ask the parent object factory if not found in this instance.
- ///
- ///
- ///
- /// A merged
- /// with overridden properties.
- ///
- public virtual RootObjectDefinition GetMergedObjectDefinition(string name, bool includingAncestors)
- {
- return GetMergedObjectDefinition(name, GetObjectDefinition(name, includingAncestors));
- }
-
- ///
- /// Return a ,
- /// even by traversing parent if the parameter is a child definition.
- ///
- ///
- /// A merged
- /// with overridden properties.
- ///
- protected virtual RootObjectDefinition GetMergedObjectDefinition(string name, IObjectDefinition definition)
- {
- if (definition == null)
- {
- return null;
- }
- else if (definition is RootObjectDefinition)
- {
- return (RootObjectDefinition) definition;
- }
- else if (definition is ChildObjectDefinition)
- {
- ChildObjectDefinition childDefinition = (ChildObjectDefinition) definition;
- RootObjectDefinition parentDefinition = null;
- if (!name.Equals(childDefinition.ParentName))
- {
- parentDefinition =
- GetMergedObjectDefinition(TransformedObjectName(childDefinition.ParentName), true);
- }
- else
- {
- if (ParentObjectFactory is AbstractObjectFactory)
- {
- parentDefinition =
- ((AbstractObjectFactory) ParentObjectFactory).GetMergedObjectDefinition(
- childDefinition.ParentName, true);
- }
- }
- if (parentDefinition == null)
- {
- throw new NoSuchObjectDefinitionException(childDefinition.ParentName,
- string.Format(
- "Parent name '{0}' is equal to object name '{1}' - "
- +
- "cannot be resolved without an AbstractObjectFactory parent.",
- childDefinition.ParentName, name));
- }
-
- RootObjectDefinition rootDefinition = CreateRootObjectDefinition(parentDefinition);
- rootDefinition.OverrideFrom(childDefinition);
- return rootDefinition;
- }
- else
- {
- throw new ObjectDefinitionStoreException(definition.ResourceDescription, name,
- "Definition is neither a RootObjectDefinition nor a ChildObjectDefinition.");
- }
- }
-/*
- ///
- /// Merges the object definitions.
- ///
- /// Object definition name.
- /// The parent definition.
- /// The child definition.
- /// Merged object definition.
- protected virtual RootObjectDefinition MergeObjectDefinitions(string name, IObjectDefinition parentDefinition,
- IObjectDefinition childDefinition)
- {
- RootObjectDefinition rootDefinition = CreateRootObjectDefinition(parentDefinition);
- rootDefinition.OverrideFrom(childDefinition);
- return rootDefinition;
- }
-*/
- ///
- /// Creates the root object definition.
- ///
- /// The template definition to base root definition on.
- /// Root object definition.
- protected virtual RootObjectDefinition CreateRootObjectDefinition(IObjectDefinition templateDefinition)
- {
- return new RootObjectDefinition(templateDefinition);
- }
-
- ///
- /// Return the registered
- /// for the
- /// given object, allowing access to its property values and constructor
- /// argument values.
- ///
- /// The name of the object.
- ///
- /// The registered
- /// .
- ///
- ///
- /// If there is no object with the given name.
- ///
- ///
- /// In the case of errors.
- ///
- public abstract IObjectDefinition GetObjectDefinition(string name);
-
- ///
- /// Return the registered
- /// for the
- /// given object, allowing access to its property values and constructor
- /// argument values.
- ///
- /// The name of the object.
- /// Whether to search parent object factories.
- ///
- /// The registered
- /// .
- ///
- ///
- /// If there is no object with the given name.
- ///
- ///
- /// In the case of errors.
- ///
- public abstract IObjectDefinition GetObjectDefinition(string name, bool includeAncestors);
-
- ///
- /// Gets the type for the given FactoryObject.
- ///
- /// The factory object instance to check.
- /// the FactoryObject's object type
- protected virtual Type GetTypeForFactoryObject(IFactoryObject factoryObject)
- {
- try
- {
- return factoryObject.ObjectType;
- }
- catch (Exception ex)
- {
- log.Warn("FactoryObject threw exception from ObjectType, despite the contract saying " +
- "that it should return null if the type of its object cannot be determined yet", ex);
- return null;
- }
- }
-
- ///
- /// Gets the object type for the given FactoryObject definition, as far as possible.
- /// Only called if there is no singleton instance registered for the target object already.
- ///
- ///
- /// The default implementation creates the FactoryObject via GetObject
- /// to call its ObjectType property. Subclasses are encouraged to optimize
- /// this, typically by just instantiating the FactoryObject but not populating it yet,
- /// trying whether its ObjectType property already returns a type.
- /// If no type found, a full FactoryObject creation as performed by this implementation
- /// should be used as fallback.
- ///
- /// Name of the object.
- /// The merged object definition for the object.
- /// The type for the object if determinable, or null otherwise
- protected virtual Type GetTypeForFactoryObject(string objectName, RootObjectDefinition mod)
- {
- if (!mod.IsSingleton)
- {
- return null;
- }
- try
- {
- IFactoryObject factoryObject = GetFactoryObject(objectName);
- return GetTypeForFactoryObject(factoryObject);
- } catch (ObjectCreationException ex)
- {
- // Can only happen when getting a FactoryObject.
- log.Debug("Ignoring object creation exception on FactoryObject type check", ex);
- return null;
- }
- }
-
- ///
- /// Predict the eventual object type (of the processed object instance) for the
- /// specified object.
- ///
- ///
- /// Does not need to handle FactoryObjects specifically, since it is only
- /// supposed to operate on the raw object type.
- /// This implementation is simplistic in that it is not able to
- /// handle factory methods and InstantiationAwareBeanPostProcessors.
- /// It only predicts the object type correctly for a standard object.
- /// To be overridden in subclasses, applying more sophisticated type detection.
- ///
- /// Name of the object.
- /// The merged object definition to determine the type for.
- /// The type of the object, or null if not predictable
- protected virtual Type PredictObjectType(string objectName, RootObjectDefinition mod)
- {
- if (StringUtils.HasText(mod.FactoryObjectName))
- {
- return null;
- }
- return ResolveObjectType(mod, objectName);
- }
-
- ///
- /// Get the object for the given object instance, either the object
- /// instance itself or its created object in case of an
- /// .
- ///
- ///
- /// The name that may include the factory dereference prefix.
- ///
- /// The object instance.
- ///
- /// The singleton instance of the object.
- ///
- protected virtual object GetObjectForInstance(string name, object instance)
- {
- //string objectName = TransformedObjectName(name);
-
- // don't let calling code try to dereference the
- // object factory if the object isn't a factory
- if (IsFactoryDereference(name) && !(instance is IFactoryObject))
- {
- throw new ObjectIsNotAFactoryException(TransformedObjectName(name), 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))
- {
- if (!IsFactoryDereference(name))
- {
-
- // return object instance from factory...
- IFactoryObject factory = (IFactoryObject) instance;
- string objectName = TransformedObjectName(name);
-
- #region Instrumentation
-
- if (log.IsDebugEnabled)
- {
- 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.");
- }
- }
- else
- {
- // the user wants the factory itself...
- if (log.IsDebugEnabled)
- {
- log.Debug(
- string.Format("Calling code asked for IFactoryObject instance for name '{0}'.",
- TransformedObjectName(name)));
- }
- }
- }
- return instance;
- }
-
- ///
- /// Obtain an object to expose from the given IFactoryObject.
- ///
- /// The IFactoryObject instance.
- /// Name of the object.
- /// The merged object definition.
- /// The object obtained from the IFactoryObject
- /// If IFactoryObject object creation failed.
- private object GetObjectFromFactoryObject(IFactoryObject factory, string objectName, RootObjectDefinition rod)
- {
- object instance;
-
- try
- {
- instance = factory.GetObject();
- }
- catch (FactoryObjectNotInitializedException ex)
- {
- throw new ObjectCurrentlyInCreationException(
- rod.ResourceDescription, objectName, ex);
- }
- catch (Exception ex)
- {
- throw new ObjectCreationException(rod.ResourceDescription, objectName,
- "FactoryObject threw exception on object creation.", ex);
- }
-
- // Do not accept a null value for a FactoryBean that's not fully
- // initialized yet: Many FactoryBeans just return null then.
- if (instance == null && IsSingletonCurrentlyInCreation(objectName)) {
- throw new ObjectCurrentlyInCreationException(rod.ResourceDescription, objectName,
- "FactoryObject which is currently in creation returned null from GetObject.");
- }
-
- if (factory is IConfigurableFactoryObject)
- {
- IConfigurableFactoryObject configurableFactory = (IConfigurableFactoryObject)factory;
-
- #region Instrumentation
-
- if (log.IsDebugEnabled)
- {
- log.Debug(string.Format("Factory object with name '{0}' is configurable.", TransformedObjectName(objectName)));
- }
-
- #endregion
-
- if (configurableFactory.ProductTemplate != null)
- {
- instance = ConfigureObject(instance,
- String.Format("{0}.ProductTemplate", objectName),
- configurableFactory.ProductTemplate);
- }
- }
-
- if (instance != null)
- {
- try
- {
- instance = PostProcessObjectFromFactoryObject(instance, objectName);
- }
- catch (Exception ex) {
- throw new ObjectCreationException(rod.ResourceDescription, objectName,
- "Post-processing of the FactoryObject's object failed.", ex);
- }
- }
-
- return instance;
- }
-
- ///
- /// Post-process the given object that has been obtained from the FactoryObject.
- /// The resulting object will be exposed for object references.
- ///
- /// The default implementation simply returns the given object
- /// as-is. Subclasses may override this, for example, to apply
- /// post-processors.
- /// The instance obtained from the IFactoryObject.
- /// Name of the object.
- /// The object instance to expose
- /// if any post-processing failed.
- protected virtual object PostProcessObjectFromFactoryObject(object instance, string objectName)
- {
- return instance;
- }
-
- ///
- /// Convenience method to pull an
- /// from this factory.
- ///
- ///
- /// The name of the factory object to be retrieved. If this name is not a valid
- /// name, it will be converted
- /// into one.
- ///
- ///
- /// The associated with the
- /// supplied .
- ///
- protected IFactoryObject GetFactoryObject(string objectName)
- {
- if (!ObjectFactoryUtils.IsFactoryDereference(objectName))
- {
- objectName = ObjectFactoryUtils.BuildFactoryObjectName(objectName);
- }
- return (IFactoryObject) GetObject(objectName);
- }
-
- ///
- /// Is the supplied a factory object dereference?
- ///
- protected bool IsFactoryDereference(string name)
- {
- return ObjectFactoryUtils.IsFactoryDereference(name);
- }
-
- ///
- /// Determines whether the type of the given object definition matches the
- /// specified target type.
- ///
- /// Allows for lazy load of the actual object type, provided that the
- /// type match can be determined otherwise.
- /// The default implementation simply delegates to the standard
- /// ResolveObjectType method. Subclasses may override this to use
- /// a differnt strategy.
- ///
- /// Name of the object (for error handling purposes).
- /// The merged object definition to determine the type for.
- /// Type to match against (never null).
- ///
- /// true if object definition matches tye specified target type; otherwise, false.
- ///
- /// if we failed to load the type."
- protected bool IsObjectTypeMatch(string objectName, RootObjectDefinition rod, Type targetType)
- {
- Type objectType = ResolveObjectType(rod, objectName);
- return (objectType != null && targetType.IsAssignableFrom(objectType));
- }
-
- ///
- /// Resolves the type of the object for the specified object definition resolving
- /// an object type name to a Type (if necessary) and storing the resolved Type
- /// in the object definition for further use.
- ///
- /// The merged object definition to dertermine the type for.
- /// Name of the object (for error handling purposes).
- ///
- protected Type ResolveObjectType(RootObjectDefinition rod, string objectName)
- {
- try
- {
- if (rod.HasObjectType)
- {
- return rod.ObjectType;
- }
- return rod.ResolveObjectType();
- } catch (TypeLoadException e)
- {
- throw new CannotLoadObjectTypeException(rod.ResourceDescription, objectName, rod.ObjectTypeName, e);
- }
- }
-
- ///
- /// Is the object (definition) with the supplied an
- /// ?
- ///
- /// The name of the object to be checked.
- ///
- /// the object (definition) with the supplied
- /// an ?
- ///
- protected bool IsFactoryObject(string name)
- {
- string objectName = TransformedObjectName(name);
- object objectInstance = GetSingleton(objectName);
- //TODO investigate
- if (IsSingletonCurrentlyInCreation(name))
- {
- throw new ObjectCurrentlyInCreationException(objectName);
- }
-
- if (objectInstance != null)
- {
- return (objectInstance is IFactoryObject);
- }
- else
- {
- RootObjectDefinition definition = GetMergedObjectDefinition(objectName, false);
- if (definition != null)
- {
- return (definition.HasObjectType && typeof(IFactoryObject).IsAssignableFrom(definition.ObjectType));
- }
- else
- {
- if (parentObjectFactory != null)
- {
- return ((AbstractObjectFactory) parentObjectFactory).IsFactoryObject(name);
- }
- else
- {
- throw new NoSuchObjectDefinitionException(objectName,
- "Cannot find definition for object [" + objectName
- + "]");
- }
- }
- }
- }
-
- ///
- /// Remove the object identified by the supplied
- /// from this factory's singleton cache.
- ///
- ///
- /// The name of the object that is to be removed from the singleton
- /// cache.
- ///
- ///
- /// If the argument is or
- /// consists wholly of whitespace characters.
- ///
- protected void RemoveSingleton(string name)
- {
- AssertUtils.ArgumentHasText(name, "name");
- lock (singletonCache)
- {
- this.singletonCache.Remove(name);
- }
- }
-
- ///
- /// Return the names of objects in the singleton cache that match the given
- /// object type (including subclasses).
- ///
- ///
- /// The class or interface to match, or for all object names.
- ///
- ///
- ///
- /// Will not consider s
- /// as the type of their created objects is not known before instantiation.
- ///
- ///
- /// Does not consider any hierarchy this factory may participate in.
- ///
- ///
- ///
- /// The names of objects in the singleton cache that match the given
- /// object type (including subclasses), or an empty array if none.
- ///
- public virtual string[] GetSingletonNames(Type type)
- {
- lock (singletonCache)
- {
- ArrayList matches = new ArrayList();
- foreach (string name in singletonCache.Keys)
- {
- object singletonObject = singletonCache[name];
- if (singletonObject != null && type.IsAssignableFrom(singletonObject.GetType())
- && !matches.Contains(name))
- {
- matches.Add(name);
- }
- }
- return (string[]) matches.ToArray(typeof(string));
- }
- }
-
- ///
- /// Determines whether the object with the given name matches the specified type.
- ///
- /// More specifically, check whether a GetObject call for the given name
- /// would return an object that is assignable to the specified target type.
- /// Translates aliases back to the corresponding canonical bean name.
- /// Will ask the parent factory if the bean cannot be found in this factory instance.
- ///
- /// The name of the object to query.
- /// Type of the target to match against.
- ///
- /// true if the object type matches; otherwise, false
- /// if it doesn't match or cannot be determined yet.
- ///
- /// Ff there is no object with the given name
- ///
- public bool IsTypeMatch(string name, Type targetType)
- {
- string objectName = TransformedObjectName(name);
- Type typeToMatch = (targetType != null ? targetType : typeof (object));
-
- //Check manually registered singletons.
- object objectInstance = GetSingleton(objectName);
- if (objectInstance != null)
- {
- if (objectInstance is IFactoryObject)
- {
- if (!IsFactoryDereference(name))
- {
- Type type = GetTypeForFactoryObject((IFactoryObject)objectInstance);
- return (type != null && typeToMatch.IsAssignableFrom(type));
- }
- else
- {
- return typeToMatch.IsAssignableFrom(objectInstance.GetType());
- }
- }
- else
- {
- return !IsFactoryDereference(name) && typeToMatch.IsAssignableFrom(objectInstance.GetType());
- }
- }
- else
- {
- // No singleton instance found -> check object definition
- IObjectFactory parentFactory = ParentObjectFactory;
- if (parentFactory != null && !ContainsObjectDefinition(name))
- {
- // No object definition found in this factory -> delegate to parent
- return parentFactory.IsTypeMatch(OriginalObjectName(name), targetType);
- }
-
- RootObjectDefinition mod = GetMergedObjectDefinition(objectName, false);
- Type objectType = PredictObjectType(objectName, mod);
-
- if (objectType == null)
- {
- return false;
- }
-
- // Check object class whether we're dealing with a FactoryObject
- if (typeof(IFactoryObject).IsAssignableFrom(objectType))
- {
- if (!IsFactoryDereference(name))
- {
- // If it's a FactoryObject, we want to look at what it creates, not the factory class.
- Type type = GetTypeForFactoryObject(objectName, mod);
- return (type != null && typeToMatch.IsAssignableFrom(type));
- }
- else
- {
- return typeToMatch.IsAssignableFrom(objectType);
- }
- }
- else
- {
- return !IsFactoryDereference(name) && typeToMatch.IsAssignableFrom(objectType);
- }
- }
- }
-
- ///
- /// Determines the of the object with the
- /// supplied .
- ///
- ///
- ///
- /// More specifically, checks the of object that
- /// would return.
- /// For an , returns the
- /// of object that the
- /// creates.
- ///
- ///
- /// Please note that (prototype) objects created via a factory method or
- /// objects are handled
- /// slightly differently, in that we don't want to needlessly create
- /// instances of such objects just to determine the
- /// of object that they create.
- ///
- ///
- /// The name of the object to query.
- ///
- /// The of the object or
- /// if not determinable.
- ///
- public virtual Type GetType(string name)
- {
- string objectName = TransformedObjectName(name);
-
- // check manually registered singletons...
- object objectInstance = GetSingleton(objectName);
-
- if (objectInstance != null)
- {
- IFactoryObject factoryObject = objectInstance as IFactoryObject;
- if (factoryObject != null & !IsFactoryDereference(objectName))
- {
- return GetTypeForFactoryObject(factoryObject);
- }
- else
- {
- return objectInstance.GetType();
- }
- }
- else
- {
- // No singleton instance found -> check bean definition.
- IObjectFactory parentFactory = ParentObjectFactory;
- if (parentFactory != null && !ContainsObjectDefinition(objectName))
- {
- // No bean definition found in this factory -> delegate to parent.
- return parentFactory.GetType(this.OriginalObjectName(name));
- }
-
- RootObjectDefinition mod = this.GetMergedObjectDefinition(objectName, false);
- Type objectType = PredictObjectType(objectName, mod);
-
- if (objectType != null && typeof (IFactoryObject).IsAssignableFrom(objectType))
- {
- if (!IsFactoryDereference(name))
- {
- // If it's a FactoryBean, we want to look at what it creates, not the factory class.
- return GetTypeForFactoryObject(objectName, mod);
- }
- else
- {
- return objectType;
- }
- }
- else
- {
- return (!IsFactoryDereference(name) ? objectType : null);
- }
- }
- }
-
- ///
- /// Determines the of the object defined
- /// by the supplied object .
- ///
- ///
- ///
- /// This, the default, implementation returns
- /// to indicate that the type cannot be determined. Subclasses are
- /// encouraged to try to determine the actual return
- /// here, matching their strategy of resolving
- /// factory methods in the
- ///
- /// implementation.
- ///
- ///
- ///
- /// The name associated with the supplied object .
- ///
- ///
- /// The
- /// that the is to be determined for.
- ///
- ///
- /// The of the object defined by the supplied
- /// object ; or if the
- /// cannot be determined.
- ///
- protected virtual Type GetTypeForFactoryMethod(string objectName, RootObjectDefinition definition)
- {
- return null;
- }
-
- ///
- /// Returns the names of the objects in the singleton cache.
- ///
- ///
- ///
- /// Does not consider any hierarchy this factory may participate in.
- ///
- ///
- /// The names of the objects in the singleton cache.
- public virtual string[] GetSingletonNames()
- {
- lock (singletonCache)
- {
- return (string[]) new ArrayList(singletonCache.Keys).ToArray(typeof(string));
- }
- }
-
- ///
- /// Returns the number of objects in the singleton cache.
- ///
- ///
- ///
- /// Does not consider any hierarchy this factory may participate in.
- ///
- ///
- /// The number of objects in the singleton cache.
- public virtual int GetSingletonCount()
- {
- lock (singletonCache)
- {
- return singletonCache.Count;
- }
- }
-
- ///
- /// Destroys the named singleton object.
- ///
- ///
- ///
- /// Delegates to
- ///
- /// if a corresponding singleton instance is found.
- ///
- ///
- ///
- /// The name of the singleton object that is to be destroyed.
- ///
- ///
- protected virtual void DestroySingleton(string name)
- {
- lock (singletonCache)
- {
- object tempObject = singletonCache[name];
- singletonCache.Remove(name);
-
- object singletonInstance = tempObject;
- if (singletonInstance != null)
- {
- DestroyObject(name, singletonInstance);
- }
- }
- }
-
- ///
- /// Check the supplied merged object definition for any possible
- /// validation errors.
- ///
- ///
- /// The object definition to be checked for validation errors.
- ///
- ///
- /// The name of the object associated with the supplied object definition.
- ///
- ///
- /// The the object may match. Can be an interface or
- /// superclass of the actual class. For example, if the value is the
- /// class, this method will succeed whatever the
- /// class of the returned instance.
- ///
- ///
- /// The arguments to use if creating a prototype using explicit arguments to
- /// a factory method. If there is no factory method and the
- /// supplied array is not , then
- /// match the argument values by type and call the object's constructor.
- ///
- ///
- /// In the case of object validation errors.
- ///
- protected void CheckMergedObjectDefinition(RootObjectDefinition mergedObjectDefinition, String objectName,
- Type requiredType, params object[] arguments)
- {
- // check if required type can match according to the object definition;
- // this is only possible at this early stage for conventional objects!
- if (mergedObjectDefinition.HasObjectType)
- {
- Type objectType = mergedObjectDefinition.ObjectType;
- if (requiredType != null && StringUtils.IsNullOrEmpty(mergedObjectDefinition.FactoryMethodName)
- && !typeof(IFactoryObject).IsAssignableFrom(objectType)
- && !requiredType.IsAssignableFrom(objectType))
- {
- throw new ObjectNotOfRequiredTypeException(objectName, requiredType, objectType);
- }
- }
- // check validity of the usage of the args parameter; this can
- // only be used for prototypes constructed via a factory method...
- if (arguments != null && arguments.Length > 0)
- {
- if (mergedObjectDefinition.IsSingleton)
- {
- throw new ObjectDefinitionStoreException("Cannot specify arguments in the GetObject () method when "
- + "referring to a singleton object definition.");
- }
- //MLP lets skip this check for now.
+ */
+ ///
+ /// Creates the root object definition.
+ ///
+ /// The template definition to base root definition on.
+ /// Root object definition.
+ protected virtual RootObjectDefinition CreateRootObjectDefinition(IObjectDefinition templateDefinition)
+ {
+ return new RootObjectDefinition(templateDefinition);
+ }
+
+ ///
+ /// Return the registered
+ /// for the
+ /// given object, allowing access to its property values and constructor
+ /// argument values.
+ ///
+ /// The name of the object.
+ ///
+ /// The registered
+ /// .
+ ///
+ ///
+ /// If there is no object with the given name.
+ ///
+ ///
+ /// In the case of errors.
+ ///
+ public abstract IObjectDefinition GetObjectDefinition(string name);
+
+ ///
+ /// Return the registered
+ /// for the
+ /// given object, allowing access to its property values and constructor
+ /// argument values.
+ ///
+ /// The name of the object.
+ /// Whether to search parent object factories.
+ ///
+ /// The registered
+ /// .
+ ///
+ ///
+ /// If there is no object with the given name.
+ ///
+ ///
+ /// In the case of errors.
+ ///
+ public abstract IObjectDefinition GetObjectDefinition(string name, bool includeAncestors);
+
+ ///
+ /// Gets the type for the given FactoryObject.
+ ///
+ /// The factory object instance to check.
+ /// the FactoryObject's object type
+ protected virtual Type GetTypeForFactoryObject(IFactoryObject factoryObject)
+ {
+ try
+ {
+ return factoryObject.ObjectType;
+ }
+ catch (Exception ex)
+ {
+ log.Warn("FactoryObject threw exception from ObjectType, despite the contract saying " +
+ "that it should return null if the type of its object cannot be determined yet", ex);
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the object type for the given FactoryObject definition, as far as possible.
+ /// Only called if there is no singleton instance registered for the target object already.
+ ///
+ ///
+ /// The default implementation creates the FactoryObject via GetObject
+ /// to call its ObjectType property. Subclasses are encouraged to optimize
+ /// this, typically by just instantiating the FactoryObject but not populating it yet,
+ /// trying whether its ObjectType property already returns a type.
+ /// If no type found, a full FactoryObject creation as performed by this implementation
+ /// should be used as fallback.
+ ///
+ /// Name of the object.
+ /// The merged object definition for the object.
+ /// The type for the object if determinable, or null otherwise
+ protected virtual Type GetTypeForFactoryObject(string objectName, RootObjectDefinition mod)
+ {
+ if (!mod.IsSingleton)
+ {
+ return null;
+ }
+ try
+ {
+ IFactoryObject factoryObject = GetFactoryObject(objectName);
+ return GetTypeForFactoryObject(factoryObject);
+ }
+ catch (ObjectCreationException ex)
+ {
+ // Can only happen when getting a FactoryObject.
+ log.Debug("Ignoring object creation exception on FactoryObject type check", ex);
+ return null;
+ }
+ }
+
+ ///
+ /// Predict the eventual object type (of the processed object instance) for the
+ /// specified object.
+ ///
+ ///
+ /// Does not need to handle FactoryObjects specifically, since it is only
+ /// supposed to operate on the raw object type.
+ /// This implementation is simplistic in that it is not able to
+ /// handle factory methods and InstantiationAwareBeanPostProcessors.
+ /// It only predicts the object type correctly for a standard object.
+ /// To be overridden in subclasses, applying more sophisticated type detection.
+ ///
+ /// Name of the object.
+ /// The merged object definition to determine the type for.
+ /// The type of the object, or null if not predictable
+ protected virtual Type PredictObjectType(string objectName, RootObjectDefinition mod)
+ {
+ if (StringUtils.HasText(mod.FactoryObjectName))
+ {
+ return null;
+ }
+ return ResolveObjectType(mod, objectName);
+ }
+
+ ///
+ /// Get the object for the given object instance, either the object
+ /// instance itself or its created object in case of an
+ /// .
+ ///
+ ///
+ /// The name that may include the factory dereference prefix.
+ ///
+ /// The object instance.
+ ///
+ /// The singleton instance of the object.
+ ///
+ protected virtual object GetObjectForInstance(string name, object instance)
+ {
+ //string objectName = TransformedObjectName(name);
+
+ // don't let calling code try to dereference the
+ // object factory if the object isn't a factory
+ if (IsFactoryDereference(name) && !(instance is IFactoryObject))
+ {
+ throw new ObjectIsNotAFactoryException(TransformedObjectName(name), 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))
+ {
+ if (!IsFactoryDereference(name))
+ {
+
+ // return object instance from factory...
+ IFactoryObject factory = (IFactoryObject)instance;
+ string objectName = TransformedObjectName(name);
+
+ #region Instrumentation
+
+ if (log.IsDebugEnabled)
+ {
+ 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.");
+ }
+ }
+ else
+ {
+ // the user wants the factory itself...
+ if (log.IsDebugEnabled)
+ {
+ log.Debug(
+ string.Format("Calling code asked for IFactoryObject instance for name '{0}'.",
+ TransformedObjectName(name)));
+ }
+ }
+ }
+ return instance;
+ }
+
+ ///
+ /// Obtain an object to expose from the given IFactoryObject.
+ ///
+ /// The IFactoryObject instance.
+ /// Name of the object.
+ /// The merged object definition.
+ /// The object obtained from the IFactoryObject
+ /// If IFactoryObject object creation failed.
+ private object GetObjectFromFactoryObject(IFactoryObject factory, string objectName, RootObjectDefinition rod)
+ {
+ object instance;
+
+ try
+ {
+ instance = factory.GetObject();
+ }
+ catch (FactoryObjectNotInitializedException ex)
+ {
+ throw new ObjectCurrentlyInCreationException(
+ rod.ResourceDescription, objectName, ex);
+ }
+ catch (Exception ex)
+ {
+ throw new ObjectCreationException(rod.ResourceDescription, objectName,
+ "FactoryObject threw exception on object creation.", ex);
+ }
+
+ // Do not accept a null value for a FactoryBean that's not fully
+ // initialized yet: Many FactoryBeans just return null then.
+ if (instance == null && IsSingletonCurrentlyInCreation(objectName))
+ {
+ throw new ObjectCurrentlyInCreationException(rod.ResourceDescription, objectName,
+ "FactoryObject which is currently in creation returned null from GetObject.");
+ }
+
+ if (factory is IConfigurableFactoryObject)
+ {
+ IConfigurableFactoryObject configurableFactory = (IConfigurableFactoryObject)factory;
+
+ #region Instrumentation
+
+ if (log.IsDebugEnabled)
+ {
+ log.Debug(string.Format("Factory object with name '{0}' is configurable.", TransformedObjectName(objectName)));
+ }
+
+ #endregion
+
+ if (configurableFactory.ProductTemplate != null)
+ {
+ instance = ConfigureObject(instance,
+ String.Format("{0}.ProductTemplate", objectName),
+ configurableFactory.ProductTemplate);
+ }
+ }
+
+ if (instance != null)
+ {
+ try
+ {
+ instance = PostProcessObjectFromFactoryObject(instance, objectName);
+ }
+ catch (Exception ex)
+ {
+ throw new ObjectCreationException(rod.ResourceDescription, objectName,
+ "Post-processing of the FactoryObject's object failed.", ex);
+ }
+ }
+
+ return instance;
+ }
+
+ ///
+ /// Post-process the given object that has been obtained from the FactoryObject.
+ /// The resulting object will be exposed for object references.
+ ///
+ /// The default implementation simply returns the given object
+ /// as-is. Subclasses may override this, for example, to apply
+ /// post-processors.
+ /// The instance obtained from the IFactoryObject.
+ /// Name of the object.
+ /// The object instance to expose
+ /// if any post-processing failed.
+ protected virtual object PostProcessObjectFromFactoryObject(object instance, string objectName)
+ {
+ return instance;
+ }
+
+ ///
+ /// Convenience method to pull an
+ /// from this factory.
+ ///
+ ///
+ /// The name of the factory object to be retrieved. If this name is not a valid
+ /// name, it will be converted
+ /// into one.
+ ///
+ ///
+ /// The associated with the
+ /// supplied .
+ ///
+ protected IFactoryObject GetFactoryObject(string objectName)
+ {
+ if (!ObjectFactoryUtils.IsFactoryDereference(objectName))
+ {
+ objectName = ObjectFactoryUtils.BuildFactoryObjectName(objectName);
+ }
+ return (IFactoryObject)GetObject(objectName);
+ }
+
+ ///
+ /// Is the supplied a factory object dereference?
+ ///
+ protected bool IsFactoryDereference(string name)
+ {
+ return ObjectFactoryUtils.IsFactoryDereference(name);
+ }
+
+ ///
+ /// Determines whether the type of the given object definition matches the
+ /// specified target type.
+ ///
+ /// Allows for lazy load of the actual object type, provided that the
+ /// type match can be determined otherwise.
+ /// The default implementation simply delegates to the standard
+ /// ResolveObjectType method. Subclasses may override this to use
+ /// a differnt strategy.
+ ///
+ /// Name of the object (for error handling purposes).
+ /// The merged object definition to determine the type for.
+ /// Type to match against (never null).
+ ///
+ /// true if object definition matches tye specified target type; otherwise, false.
+ ///
+ /// if we failed to load the type."
+ protected bool IsObjectTypeMatch(string objectName, RootObjectDefinition rod, Type targetType)
+ {
+ Type objectType = ResolveObjectType(rod, objectName);
+ return (objectType != null && targetType.IsAssignableFrom(objectType));
+ }
+
+ ///
+ /// Resolves the type of the object for the specified object definition resolving
+ /// an object type name to a Type (if necessary) and storing the resolved Type
+ /// in the object definition for further use.
+ ///
+ /// The merged object definition to dertermine the type for.
+ /// Name of the object (for error handling purposes).
+ ///
+ protected Type ResolveObjectType(RootObjectDefinition rod, string objectName)
+ {
+ try
+ {
+ if (rod.HasObjectType)
+ {
+ return rod.ObjectType;
+ }
+ return rod.ResolveObjectType();
+ }
+ catch (TypeLoadException e)
+ {
+ throw new CannotLoadObjectTypeException(rod.ResourceDescription, objectName, rod.ObjectTypeName, e);
+ }
+ }
+
+ ///
+ /// Is the object (definition) with the supplied an
+ /// ?
+ ///
+ /// The name of the object to be checked.
+ ///
+ /// the object (definition) with the supplied
+ /// an ?
+ ///
+ protected bool IsFactoryObject(string name)
+ {
+ string objectName = TransformedObjectName(name);
+ object objectInstance = GetSingleton(objectName);
+ //TODO investigate
+ if (IsSingletonCurrentlyInCreation(name))
+ {
+ throw new ObjectCurrentlyInCreationException(objectName);
+ }
+
+ if (objectInstance != null)
+ {
+ return (objectInstance is IFactoryObject);
+ }
+ else
+ {
+ RootObjectDefinition definition = GetMergedObjectDefinition(objectName, false);
+ if (definition != null)
+ {
+ return (definition.HasObjectType && typeof(IFactoryObject).IsAssignableFrom(definition.ObjectType));
+ }
+ else
+ {
+ if (parentObjectFactory != null)
+ {
+ return ((AbstractObjectFactory)parentObjectFactory).IsFactoryObject(name);
+ }
+ else
+ {
+ throw new NoSuchObjectDefinitionException(objectName,
+ "Cannot find definition for object [" + objectName
+ + "]");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Remove the object identified by the supplied
+ /// from this factory's singleton cache.
+ ///
+ ///
+ /// The name of the object that is to be removed from the singleton
+ /// cache.
+ ///
+ ///
+ /// If the argument is or
+ /// consists wholly of whitespace characters.
+ ///
+ protected void RemoveSingleton(string name)
+ {
+ AssertUtils.ArgumentHasText(name, "name");
+ lock (singletonCache)
+ {
+ this.singletonCache.Remove(name);
+ }
+ }
+
+ ///
+ /// Return the names of objects in the singleton cache that match the given
+ /// object type (including subclasses).
+ ///
+ ///
+ /// The class or interface to match, or for all object names.
+ ///
+ ///
+ ///
+ /// Will not consider s
+ /// as the type of their created objects is not known before instantiation.
+ ///
+ ///
+ /// Does not consider any hierarchy this factory may participate in.
+ ///
+ ///
+ ///
+ /// The names of objects in the singleton cache that match the given
+ /// object type (including subclasses), or an empty array if none.
+ ///
+ public virtual string[] GetSingletonNames(Type type)
+ {
+ lock (singletonCache)
+ {
+ ArrayList matches = new ArrayList();
+ foreach (string name in singletonCache.Keys)
+ {
+ object singletonObject = singletonCache[name];
+ if (singletonObject != null && type.IsAssignableFrom(singletonObject.GetType())
+ && !matches.Contains(name))
+ {
+ matches.Add(name);
+ }
+ }
+ return (string[])matches.ToArray(typeof(string));
+ }
+ }
+
+ ///
+ /// Determines whether the object with the given name matches the specified type.
+ ///
+ /// More specifically, check whether a GetObject call for the given name
+ /// would return an object that is assignable to the specified target type.
+ /// Translates aliases back to the corresponding canonical bean name.
+ /// Will ask the parent factory if the bean cannot be found in this factory instance.
+ ///
+ /// The name of the object to query.
+ /// Type of the target to match against.
+ ///
+ /// true if the object type matches; otherwise, false
+ /// if it doesn't match or cannot be determined yet.
+ ///
+ /// Ff there is no object with the given name
+ ///
+ public bool IsTypeMatch(string name, Type targetType)
+ {
+ string objectName = TransformedObjectName(name);
+ Type typeToMatch = (targetType != null ? targetType : typeof(object));
+
+ //Check manually registered singletons.
+ object objectInstance = GetSingleton(objectName);
+ if (objectInstance != null)
+ {
+ if (objectInstance is IFactoryObject)
+ {
+ if (!IsFactoryDereference(name))
+ {
+ Type type = GetTypeForFactoryObject((IFactoryObject)objectInstance);
+ return (type != null && typeToMatch.IsAssignableFrom(type));
+ }
+ else
+ {
+ return typeToMatch.IsAssignableFrom(objectInstance.GetType());
+ }
+ }
+ else
+ {
+ return !IsFactoryDereference(name) && typeToMatch.IsAssignableFrom(objectInstance.GetType());
+ }
+ }
+ else
+ {
+ // No singleton instance found -> check object definition
+ IObjectFactory parentFactory = ParentObjectFactory;
+ if (parentFactory != null && !ContainsObjectDefinition(name))
+ {
+ // No object definition found in this factory -> delegate to parent
+ return parentFactory.IsTypeMatch(OriginalObjectName(name), targetType);
+ }
+
+ RootObjectDefinition mod = GetMergedObjectDefinition(objectName, false);
+ Type objectType = PredictObjectType(objectName, mod);
+
+ if (objectType == null)
+ {
+ return false;
+ }
+
+ // Check object class whether we're dealing with a FactoryObject
+ if (typeof(IFactoryObject).IsAssignableFrom(objectType))
+ {
+ if (!IsFactoryDereference(name))
+ {
+ // If it's a FactoryObject, we want to look at what it creates, not the factory class.
+ Type type = GetTypeForFactoryObject(objectName, mod);
+ return (type != null && typeToMatch.IsAssignableFrom(type));
+ }
+ else
+ {
+ return typeToMatch.IsAssignableFrom(objectType);
+ }
+ }
+ else
+ {
+ return !IsFactoryDereference(name) && typeToMatch.IsAssignableFrom(objectType);
+ }
+ }
+ }
+
+ ///
+ /// Determines the of the object with the
+ /// supplied .
+ ///
+ ///
+ ///
+ /// More specifically, checks the of object that
+ /// would return.
+ /// For an , returns the
+ /// of object that the
+ /// creates.
+ ///
+ ///
+ /// Please note that (prototype) objects created via a factory method or
+ /// objects are handled
+ /// slightly differently, in that we don't want to needlessly create
+ /// instances of such objects just to determine the
+ /// of object that they create.
+ ///
+ ///
+ /// The name of the object to query.
+ ///
+ /// The of the object or
+ /// if not determinable.
+ ///
+ public virtual Type GetType(string name)
+ {
+ string objectName = TransformedObjectName(name);
+
+ // check manually registered singletons...
+ object objectInstance = GetSingleton(objectName);
+
+ if (objectInstance != null)
+ {
+ IFactoryObject factoryObject = objectInstance as IFactoryObject;
+ if (factoryObject != null & !IsFactoryDereference(objectName))
+ {
+ return GetTypeForFactoryObject(factoryObject);
+ }
+ else
+ {
+ return objectInstance.GetType();
+ }
+ }
+ else
+ {
+ // No singleton instance found -> check bean definition.
+ IObjectFactory parentFactory = ParentObjectFactory;
+ if (parentFactory != null && !ContainsObjectDefinition(objectName))
+ {
+ // No bean definition found in this factory -> delegate to parent.
+ return parentFactory.GetType(this.OriginalObjectName(name));
+ }
+
+ RootObjectDefinition mod = this.GetMergedObjectDefinition(objectName, false);
+ Type objectType = PredictObjectType(objectName, mod);
+
+ if (objectType != null && typeof(IFactoryObject).IsAssignableFrom(objectType))
+ {
+ if (!IsFactoryDereference(name))
+ {
+ // If it's a FactoryBean, we want to look at what it creates, not the factory class.
+ return GetTypeForFactoryObject(objectName, mod);
+ }
+ else
+ {
+ return objectType;
+ }
+ }
+ else
+ {
+ return (!IsFactoryDereference(name) ? objectType : null);
+ }
+ }
+ }
+
+ ///
+ /// Determines the of the object defined
+ /// by the supplied object .
+ ///
+ ///
+ ///
+ /// This, the default, implementation returns
+ /// to indicate that the type cannot be determined. Subclasses are
+ /// encouraged to try to determine the actual return
+ /// here, matching their strategy of resolving
+ /// factory methods in the
+ ///
+ /// implementation.
+ ///
+ ///
+ ///
+ /// The name associated with the supplied object .
+ ///
+ ///
+ /// The
+ /// that the is to be determined for.
+ ///
+ ///
+ /// The of the object defined by the supplied
+ /// object ; or if the
+ /// cannot be determined.
+ ///
+ protected virtual Type GetTypeForFactoryMethod(string objectName, RootObjectDefinition definition)
+ {
+ return null;
+ }
+
+ ///
+ /// Returns the names of the objects in the singleton cache.
+ ///
+ ///
+ ///
+ /// Does not consider any hierarchy this factory may participate in.
+ ///
+ ///
+ /// The names of the objects in the singleton cache.
+ public virtual string[] GetSingletonNames()
+ {
+ lock (singletonCache)
+ {
+ return (string[])new ArrayList(singletonCache.Keys).ToArray(typeof(string));
+ }
+ }
+
+ ///
+ /// Returns the number of objects in the singleton cache.
+ ///
+ ///
+ ///
+ /// Does not consider any hierarchy this factory may participate in.
+ ///
+ ///
+ /// The number of objects in the singleton cache.
+ public virtual int GetSingletonCount()
+ {
+ lock (singletonCache)
+ {
+ return singletonCache.Count;
+ }
+ }
+
+ ///
+ /// Destroys the named singleton object.
+ ///
+ ///
+ ///
+ /// Delegates to
+ ///
+ /// if a corresponding singleton instance is found.
+ ///
+ ///
+ ///
+ /// The name of the singleton object that is to be destroyed.
+ ///
+ ///
+ protected virtual void DestroySingleton(string name)
+ {
+ lock (singletonCache)
+ {
+ object tempObject = singletonCache[name];
+ singletonCache.Remove(name);
+
+ object singletonInstance = tempObject;
+ if (singletonInstance != null)
+ {
+ DestroyObject(name, singletonInstance);
+ }
+ }
+ }
+
+ ///
+ /// Check the supplied merged object definition for any possible
+ /// validation errors.
+ ///
+ ///
+ /// The object definition to be checked for validation errors.
+ ///
+ ///
+ /// The name of the object associated with the supplied object definition.
+ ///
+ ///
+ /// The the object may match. Can be an interface or
+ /// superclass of the actual class. For example, if the value is the
+ /// class, this method will succeed whatever the
+ /// class of the returned instance.
+ ///
+ ///
+ /// The arguments to use if creating a prototype using explicit arguments to
+ /// a factory method. If there is no factory method and the
+ /// supplied array is not , then
+ /// match the argument values by type and call the object's constructor.
+ ///
+ ///
+ /// In the case of object validation errors.
+ ///
+ protected void CheckMergedObjectDefinition(RootObjectDefinition mergedObjectDefinition, String objectName,
+ Type requiredType, params object[] arguments)
+ {
+ // check if required type can match according to the object definition;
+ // this is only possible at this early stage for conventional objects!
+ if (mergedObjectDefinition.HasObjectType)
+ {
+ Type objectType = mergedObjectDefinition.ObjectType;
+ if (requiredType != null && StringUtils.IsNullOrEmpty(mergedObjectDefinition.FactoryMethodName)
+ && !typeof(IFactoryObject).IsAssignableFrom(objectType)
+ && !requiredType.IsAssignableFrom(objectType))
+ {
+ throw new ObjectNotOfRequiredTypeException(objectName, requiredType, objectType);
+ }
+ }
+ // check validity of the usage of the args parameter; this can
+ // only be used for prototypes constructed via a factory method...
+ if (arguments != null && arguments.Length > 0)
+ {
+ if (mergedObjectDefinition.IsSingleton)
+ {
+ throw new ObjectDefinitionStoreException("Cannot specify arguments in the GetObject () method when "
+ + "referring to a singleton object definition.");
+ }
+ //MLP lets skip this check for now.
/*
- else if (StringUtils.IsNullOrEmpty(mergedObjectDefinition.FactoryMethodName))
- {
- throw new ObjectDefinitionStoreException(
- "Can only specify arguments in the GetObject () method in " +
- "conjunction with a factory method.");
- }
- */
- }
- }
-
- ///
- /// Gets the temporary object that is placed
- /// into the singleton cache during object resolution.
- ///
- protected object TemporarySingletonPlaceHolder
- {
- get { return CURRENTLY_IN_CREATION; }
- }
-
- #endregion
-
- #region Fields
-
- ///
- /// Parent object factory, for object inheritance support
- ///
- private IObjectFactory parentObjectFactory;
-
- ///
- /// Dependency types to ignore on dependency check and autowire, as Set of
- /// Type objects: for example, string. Default is none.
- ///
- private ISet ignoreDependencyTypes = new HybridSet();
-
-
- ///
- /// ObjectPostProcessors to apply in CreateObject
- ///
- private IList objectPostProcessors = new ArrayList();
-
- ///
- /// Indicates whether any IInstantiationAwareBeanPostProcessors have been registered
- ///
- private bool hasInstantiationAwareBeanPostProcessors;
-
- ///
- /// Indicates whether any IDestructionAwareBeanPostProcessors have been registered
- ///
- private bool hasDestructionAwareBeanPostProcessors;
-
- private IDictionary aliasMap;
- private IDictionary singletonCache;
- private IDictionary singletonsInCreation;
-
- #endregion
-
- #region IHierarchicalObjectFactory Members
-
- ///
- /// The parent object factory, or if there is none.
- ///
- ///
- /// The parent object factory, or if there is none.
- ///
- public IObjectFactory ParentObjectFactory
- {
- get { return parentObjectFactory; }
- set { parentObjectFactory = value; }
- }
-
- #endregion
-
- #region IObjectFactory Members
-
- ///
- /// Is this object a singleton?
- ///
- ///
- public bool IsSingleton(string name)
- {
- string objectName = TransformedObjectName(name);
- object objectInstance = this.GetSingleton(objectName);
- if (objectInstance != null)
- {
- IFactoryObject factoryObject = objectInstance as IFactoryObject;
- if (factoryObject != null)
- {
- return IsFactoryDereference(name) || factoryObject.IsSingleton;
- }
- else
- {
- return !IsFactoryDereference(name);
- }
- }
- else
- {
- // No singleton instance found -> check object definition
- IObjectFactory pof = ParentObjectFactory;
- if (pof != null && !ContainsObjectDefinition(objectName))
- {
- // No object definition found in this factory -> delegate to parent
- return pof.IsSingleton(OriginalObjectName(name));
- }
- RootObjectDefinition od = GetMergedObjectDefinition(objectName, false);
-
- // In case of IFactoryObject, return singleton status of created object if not a dereference
- if (od.IsSingleton)
- {
- if (IsObjectTypeMatch(objectName, od, typeof(IFactoryObject)))
- {
- if (IsFactoryDereference(name))
- {
- return true;
- }
- IFactoryObject factoryObject =
- (IFactoryObject) GetObject(ObjectFactoryUtils.BuildFactoryObjectName(objectName));
- return factoryObject.IsSingleton;
- }
- else
- {
- return !IsFactoryDereference(name);
- }
- }
- else
- {
- return false;
- }
- }
- }
-
- ///
- /// Determines whether the specified object name is prototype. That is, will GetObject
- /// always return independent instances?
- ///
- /// The name of the object to query
- ///
- /// true if the specified object name will always deliver independent instances; otherwise, false.
- ///
- /// This method returning false does not clearly indicate a singleton object.
- /// It indicated non-independent instances, which may correspond to a scoped object as
- /// well. use the IsSingleton property to explicitly check for a shared
- /// singleton instance.
- /// Translates aliases back to the corresponding canonical object name. Will ask the
- /// parent factory if the object can not be found in this factory instance.
- ///
- ///
- /// if there is no object with the given name.
- public bool IsPrototype(string name)
- {
- string objectName = TransformedObjectName(name);
- IObjectFactory parentFactory = ParentObjectFactory;
- if (parentFactory != null && !this.ContainsObjectDefinition(objectName))
- {
- // No object definition found in this factory -> delegate to parent
- return parentFactory.IsPrototype(OriginalObjectName(name));
- }
-
- RootObjectDefinition od = GetMergedObjectDefinition(objectName, false);
-
- // In case of FactoryObject, return singleton status of created object if not a dereference
- if (od.IsPrototype)
- {
- return (!IsFactoryDereference(name) || IsObjectTypeMatch(objectName, od, typeof(IFactoryObject)));
- }
- else
- {
- // not a prototype, however factory object may still produce a prototype object
- if (IsFactoryDereference(name) && IsObjectTypeMatch(objectName, od, typeof (IFactoryObject)))
- {
- IFactoryObject factoryObject = GetFactoryObject(objectName);
- return (!factoryObject.IsSingleton);
- }
- else
- {
- return false;
- }
- }
- }
-
- ///
- /// Does this object factory contain an object with the given name?
- ///
- ///
- /// This method does not (and it should not) check if the specified
- /// object exists in one of the parent object factories. If it did,
- /// message sources and event registries within application context
- /// hierarchy would have circular references, which would cause stack
- /// overflows during message lookup, for example. (A. Seovic)
- ///
- /// .
- public bool ContainsObject(string name)
- {
- string objectName = TransformedObjectName(name);
- lock (singletonCache)
- {
- if (singletonCache.Contains(objectName))
- {
- return true;
- }
- }
- if (ContainsObjectDefinition(objectName))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- ///
- /// Return the aliases for the given object name, if defined.
- ///
- /// .
- public string[] GetAliases(string name)
- {
- string objectName = TransformedObjectName(name);
- // check if object actually exists in this object factory...
- bool isInSingletonCache = false;
- lock(singletonCache)
- {
- isInSingletonCache = singletonCache.Contains(objectName);
- }
- if (isInSingletonCache || ContainsObjectDefinition(objectName))
- {
- // if found, gather aliases...
- ArrayList matches = new ArrayList();
- lock (aliasMap)
- {
- foreach (DictionaryEntry aliasEntry in aliasMap)
- {
- if (aliasEntry.Value.Equals(objectName))
- {
- matches.Add(aliasEntry.Key);
- }
- }
- }
- return (string[]) matches.ToArray(typeof(string));
- }
- else
- {
- // not found, so check parent...
- if (ParentObjectFactory != null)
- {
- return ParentObjectFactory.GetAliases(objectName);
- }
- throw new NoSuchObjectDefinitionException(objectName, ToString());
- }
- }
-
- ///
- /// Return an instance (possibly shared or independent) of the given object name.
- ///
- /// .
- public object this[string name]
- {
- get { return GetObject(name); }
- }
-
- ///
- /// Return an instance (possibly shared or independent) of the given object name.
- ///
- /// .
- public object GetObject(string name)
- {
- return GetObject(name, typeof(object), ObjectUtils.EmptyObjects);
- }
-
- ///
- /// Return an instance (possibly shared or independent) of the given object name.
- ///
- ///
- ///
- /// This method allows an object factory to be used as a replacement for the
- /// Singleton or Prototype design pattern.
- ///
- ///
- /// Note that callers should retain references to returned objects. There is no
- /// guarantee that this method will be implemented to be efficient. For example,
- /// it may be synchronized, or may need to run an RDBMS query.
- ///
- ///
- /// Will ask the parent factory if the object cannot be found in this factory
- /// instance.
- ///
- ///
- /// The name of the object to return.
- ///
- /// The arguments to use if creating a prototype using explicit arguments to
- /// a static factory method. If there is no factory method and the
- /// arguments are not null, then match the argument values by type and
- /// call the object's constructor.
- ///
- /// The instance of the object.
- ///
- /// If there's no such object definition.
- ///
- ///
- /// If the object could not be created.
- ///
- ///
- /// If the supplied is .
- ///
- public object GetObject(string name, object[] arguments)
- {
- object instance = null;
- string objectName = TransformedObjectName(name);
-
- // check if object definition exists
- RootObjectDefinition mergedObjectDefinition = null;
- mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
- if (mergedObjectDefinition == null)
- {
- if (ParentObjectFactory != null)
- {
- return ParentObjectFactory.GetObject(name, arguments);
- }
- throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
- }
-
- // Override constructor values and configure as a prototype
- RootObjectDefinition tmpObjectDefinition = new RootObjectDefinition(mergedObjectDefinition);
- tmpObjectDefinition.ConstructorArgumentValues = null;
- tmpObjectDefinition.IsSingleton = false;
-
- // create a new instance...
- instance = CreateObject(name, tmpObjectDefinition, arguments);
-
- return GetObjectForInstance(name, instance);
- }
-
- ///
- /// Tries to find a cached object for the specified name.
- ///
- /// Teh object name to look for.
- /// The cached object if found, otherwise.
- protected virtual object GetSingleton(string objectName)
- {
- lock (singletonCache)
- {
- return singletonCache[objectName];
- }
- }
-
- ///
- /// Creates a singleton instance for the specified object name and definition.
- ///
- ///
- /// The object name (will be used as the key in the singleton cache key).
- ///
- /// The object definition.
- ///
- /// The arguments to use if creating a prototype using explicit arguments to
- /// a static factory method. If there is no factory method and the
- /// arguments are not null, then match the argument values by type and
- /// call the object's constructor.
- ///
- /// The created object instance.
- protected virtual object CreateAndCacheSingletonInstance(string objectName,
- RootObjectDefinition objectDefinition,
- object[] arguments)
- {
- lock (singletonCache)
- {
- object sharedInstance = singletonCache[objectName];
- if (sharedInstance == null)
- {
- #region Instrumentation
-
- if (log.IsDebugEnabled)
- {
- log.Debug("Creating shared instance of singleton object '" + objectName + "'");
- }
-
- #endregion
-
- BeforeSingletonCreation(objectName);
- try
- {
- sharedInstance = CreateObject(objectName, objectDefinition, arguments);
- }
- finally
- {
- AfterSingletonCreation(objectName);
- }
- AddSingleton(objectName, sharedInstance);
- }
- return sharedInstance;
- }
- }
-
- private void AfterSingletonCreation(string name)
- {
- if (!singletonsInCreation.Contains(name))
- {
- throw new InvalidOperationException("Singleton " + name + " isn't currently in creation.");
- }
- singletonsInCreation.Remove(name);
- }
-
- private void BeforeSingletonCreation(string name)
- {
- if (this.singletonsInCreation.Contains(name))
- {
- throw new ObjectCurrentlyInCreationException(name);
- }
- singletonsInCreation.Add(name, emptyObject);
- }
-
- ///
- /// Return an instance (possibly shared or independent) of the given object name.
- ///
- ///
- public object GetObject(string name, Type requiredType)
- {
- return GetObject(name, requiredType, ObjectUtils.EmptyObjects);
- }
-
- ///
- /// Injects dependencies into the supplied instance
- /// using the named object definition.
- ///
- ///
- public abstract object ConfigureObject(object target, string name);
-
- ///
- /// Injects dependencies into the supplied instance
- /// using the supplied .
- ///
- ///
- public abstract object ConfigureObject(object target, string name, IObjectDefinition definition);
-
- #endregion
-
- #region IConfigurableObjectFactory Members
-
- ///
- /// Destroy all cached singletons in this factory.
- ///
- public virtual void Dispose()
- {
- #region Instrumentation
-
- if (log.IsDebugEnabled)
- {
- log.Debug(string.Format("Destroying singletons in factory [{0}].", this));
- }
-
- #endregion
-
- lock (singletonCache)
- {
- // copy the keys into a new set, 'cos we are going to modifying the
- // original collection (_singletonCache) as we destroy each singleton.
- ISet keys = new HashedSet(singletonCache.Keys);
- foreach (string name in keys)
- {
- DestroySingleton(name);
- }
- }
- }
-
- ///
- /// Ignore the given dependency type for autowiring
- ///
- /// .
- public void IgnoreDependencyType(Type type)
- {
- IgnoredDependencyTypes.Add(type);
- }
-
- ///
- /// Determines whether the specified object name is currently in creation..
- ///
- /// Name of the object.
- ///
- /// true if the specified object name is currently in creation; otherwise, false.
- ///
- public bool IsCurrentlyInCreation(string objectName)
- {
- return IsSingletonCurrentlyInCreation(objectName) || IsPrototypeCurrentlyInCreation(objectName);
- }
-
- private bool IsPrototypeCurrentlyInCreation(string name)
- {
- //TODO
- return false;
- }
-
- private bool IsSingletonCurrentlyInCreation(string name)
- {
- if (this.singletonsInCreation.Contains(name))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- ///
- /// Add a new
- /// that will get applied to objects created by this factory.
- ///
- ///
- /// The
- /// to register.
- ///
- /// .
- public void AddObjectPostProcessor(IObjectPostProcessor objectPostProcessor)
- {
- // ensure the same instance doesn't get registered twice
- if (!ObjectPostProcessors.Contains(objectPostProcessor))
- {
- ObjectPostProcessors.Add(objectPostProcessor);
- }
- if (typeof (IInstantiationAwareObjectPostProcessor).IsInstanceOfType(objectPostProcessor))
- {
- hasInstantiationAwareBeanPostProcessors = true;
- }
- if (typeof (IDestructionAwareObjectPostProcessor).IsInstanceOfType(objectPostProcessor))
- {
- hasDestructionAwareBeanPostProcessors = true;
- }
- }
-
- ///
- /// Returns the current number of registered
- /// s.
- ///
- ///
- /// The current number of registered
- /// s.
- ///
- /// .
- public int ObjectPostProcessorCount
- {
- get { return ObjectPostProcessors.Count; }
- }
-
- ///
- /// Given an object name, create an alias.
- ///
- /// .
- public void RegisterAlias(string name, string alias)
- {
- #region Sanity Checks
-
- AssertUtils.ArgumentHasText(name, "The object name must not be empty.");
- AssertUtils.ArgumentHasText(alias, "The alias must not be empty.");
-
- #endregion
-
- #region Instrumentation
-
- if (log.IsDebugEnabled)
- {
- log.Debug(string.Format("Registering alias '{0}' for object with name '{1}'.", alias, name));
- }
-
- #endregion
-
- lock (aliasMap)
- {
- object registeredName = aliasMap[alias];
- if (registeredName != null)
+ else if (StringUtils.IsNullOrEmpty(mergedObjectDefinition.FactoryMethodName))
{
throw new ObjectDefinitionStoreException(
- string.Format(
- "Cannot register alias '{0}' for object with name '{1}': it's already registered for object name '{2}'.",
- alias, name, registeredName));
+ "Can only specify arguments in the GetObject () method in " +
+ "conjunction with a factory method.");
}
- aliasMap[alias] = name;
- }
- }
-
- ///
- /// Register the given existing object as singleton in the object factory,
- /// under the given object name.
- ///
- /// .
- public void RegisterSingleton(string name, object singletonObject)
- {
- AssertUtils.ArgumentHasText(name, "name", "The singleton object cannot be registered under an empty name.");
- lock (singletonCache)
- {
- object oldObject = singletonCache[name];
- if (oldObject != null)
- {
- throw new ObjectDefinitionStoreException(
- string.Format(
- "Could not register object [{0}] under object name '{1}': there's already object [{2}] bound.",
- singletonObject, name, oldObject));
- }
- AddSingleton(name, singletonObject);
- }
- }
-
- ///
- /// Register the given custom
- /// for all properties of the given .
- ///
- /// .
- public void RegisterCustomConverter(Type requiredType, TypeConverter converter)
- {
- AssertUtils.ArgumentNotNull(requiredType, "requiredType");
- TypeConverterRegistry.RegisterConverter(requiredType, converter);
- }
-
- ///
- /// Does this object factory contains a singleton instance with the
- /// supplied ?
- ///
- ///
- public bool ContainsSingleton(string name)
- {
- AssertUtils.ArgumentHasText(name, "name");
- lock (singletonCache)
- {
- return singletonCache.Contains(name);
- }
- }
-
- #endregion
- }
+ */
+ }
+ }
+
+ ///
+ /// Gets the temporary object that is placed
+ /// into the singleton cache during object resolution.
+ ///
+ protected object TemporarySingletonPlaceHolder
+ {
+ get { return CURRENTLY_IN_CREATION; }
+ }
+
+ #endregion
+
+ #region Fields
+
+ ///
+ /// Parent object factory, for object inheritance support
+ ///
+ private IObjectFactory parentObjectFactory;
+
+ ///
+ /// Dependency types to ignore on dependency check and autowire, as Set of
+ /// Type objects: for example, string. Default is none.
+ ///
+ private ISet ignoreDependencyTypes = new HybridSet();
+
+
+ ///
+ /// ObjectPostProcessors to apply in CreateObject
+ ///
+ private IList objectPostProcessors = new ArrayList();
+
+ ///
+ /// Indicates whether any IInstantiationAwareBeanPostProcessors have been registered
+ ///
+ private bool hasInstantiationAwareBeanPostProcessors;
+
+ ///
+ /// Indicates whether any IDestructionAwareBeanPostProcessors have been registered
+ ///
+ private bool hasDestructionAwareBeanPostProcessors;
+
+ private bool caseSensitive;
+ private IDictionary aliasMap;
+ private IDictionary singletonCache;
+ private IDictionary singletonsInCreation;
+
+ #endregion
+
+ #region IHierarchicalObjectFactory Members
+
+ ///
+ /// The parent object factory, or if there is none.
+ ///
+ ///
+ /// The parent object factory, or if there is none.
+ ///
+ public IObjectFactory ParentObjectFactory
+ {
+ get { return parentObjectFactory; }
+ set { parentObjectFactory = value; }
+ }
+
+ #endregion
+
+ #region IObjectFactory Members
+
+ ///
+ /// Is this object a singleton?
+ ///
+ ///
+ public bool IsSingleton(string name)
+ {
+ string objectName = TransformedObjectName(name);
+ object objectInstance = this.GetSingleton(objectName);
+ if (objectInstance != null)
+ {
+ IFactoryObject factoryObject = objectInstance as IFactoryObject;
+ if (factoryObject != null)
+ {
+ return IsFactoryDereference(name) || factoryObject.IsSingleton;
+ }
+ else
+ {
+ return !IsFactoryDereference(name);
+ }
+ }
+ else
+ {
+ // No singleton instance found -> check object definition
+ IObjectFactory pof = ParentObjectFactory;
+ if (pof != null && !ContainsObjectDefinition(objectName))
+ {
+ // No object definition found in this factory -> delegate to parent
+ return pof.IsSingleton(OriginalObjectName(name));
+ }
+ RootObjectDefinition od = GetMergedObjectDefinition(objectName, false);
+
+ // In case of IFactoryObject, return singleton status of created object if not a dereference
+ if (od.IsSingleton)
+ {
+ if (IsObjectTypeMatch(objectName, od, typeof(IFactoryObject)))
+ {
+ if (IsFactoryDereference(name))
+ {
+ return true;
+ }
+ IFactoryObject factoryObject =
+ (IFactoryObject)GetObject(ObjectFactoryUtils.BuildFactoryObjectName(objectName));
+ return factoryObject.IsSingleton;
+ }
+ else
+ {
+ return !IsFactoryDereference(name);
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Determines whether the specified object name is prototype. That is, will GetObject
+ /// always return independent instances?
+ ///
+ /// The name of the object to query
+ ///
+ /// true if the specified object name will always deliver independent instances; otherwise, false.
+ ///
+ /// This method returning false does not clearly indicate a singleton object.
+ /// It indicated non-independent instances, which may correspond to a scoped object as
+ /// well. use the IsSingleton property to explicitly check for a shared
+ /// singleton instance.
+ /// Translates aliases back to the corresponding canonical object name. Will ask the
+ /// parent factory if the object can not be found in this factory instance.
+ ///
+ ///
+ /// if there is no object with the given name.
+ public bool IsPrototype(string name)
+ {
+ string objectName = TransformedObjectName(name);
+ IObjectFactory parentFactory = ParentObjectFactory;
+ if (parentFactory != null && !this.ContainsObjectDefinition(objectName))
+ {
+ // No object definition found in this factory -> delegate to parent
+ return parentFactory.IsPrototype(OriginalObjectName(name));
+ }
+
+ RootObjectDefinition od = GetMergedObjectDefinition(objectName, false);
+
+ // In case of FactoryObject, return singleton status of created object if not a dereference
+ if (od.IsPrototype)
+ {
+ return (!IsFactoryDereference(name) || IsObjectTypeMatch(objectName, od, typeof(IFactoryObject)));
+ }
+ else
+ {
+ // not a prototype, however factory object may still produce a prototype object
+ if (IsFactoryDereference(name) && IsObjectTypeMatch(objectName, od, typeof(IFactoryObject)))
+ {
+ IFactoryObject factoryObject = GetFactoryObject(objectName);
+ return (!factoryObject.IsSingleton);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ /// Does this object factory contain an object with the given name?
+ ///
+ ///
+ /// This method does not (and it should not) check if the specified
+ /// object exists in one of the parent object factories. If it did,
+ /// message sources and event registries within application context
+ /// hierarchy would have circular references, which would cause stack
+ /// overflows during message lookup, for example. (A. Seovic)
+ ///
+ /// .
+ public bool ContainsObject(string name)
+ {
+ string objectName = TransformedObjectName(name);
+ lock (singletonCache)
+ {
+ if (singletonCache.Contains(objectName))
+ {
+ return true;
+ }
+ }
+ if (ContainsObjectDefinition(objectName))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Return the aliases for the given object name, if defined.
+ ///
+ /// .
+ public string[] GetAliases(string name)
+ {
+ string objectName = TransformedObjectName(name);
+ // check if object actually exists in this object factory...
+ bool isInSingletonCache = false;
+ lock (singletonCache)
+ {
+ isInSingletonCache = singletonCache.Contains(objectName);
+ }
+ if (isInSingletonCache || ContainsObjectDefinition(objectName))
+ {
+ // if found, gather aliases...
+ ArrayList matches = new ArrayList();
+ lock (aliasMap)
+ {
+ foreach (DictionaryEntry aliasEntry in aliasMap)
+ {
+ if (0 == string.Compare((string)aliasEntry.Value, objectName, !this.IsCaseSensitive))
+ {
+ matches.Add(aliasEntry.Key);
+ }
+ }
+ }
+ return (string[])matches.ToArray(typeof(string));
+ }
+
+ // not found, so check parent...
+ if (ParentObjectFactory != null)
+ {
+ return ParentObjectFactory.GetAliases(objectName);
+ }
+ throw new NoSuchObjectDefinitionException(objectName, ToString());
+ }
+
+ ///
+ /// Return an instance (possibly shared or independent) of the given object name.
+ ///
+ /// .
+ public object this[string name]
+ {
+ get { return GetObject(name); }
+ }
+
+ ///
+ /// Return an instance (possibly shared or independent) of the given object name.
+ ///
+ /// .
+ public object GetObject(string name)
+ {
+ return GetObject(name, typeof(object), ObjectUtils.EmptyObjects);
+ }
+
+ ///
+ /// Return an instance (possibly shared or independent) of the given object name.
+ ///
+ ///
+ ///
+ /// This method allows an object factory to be used as a replacement for the
+ /// Singleton or Prototype design pattern.
+ ///
+ ///
+ /// Note that callers should retain references to returned objects. There is no
+ /// guarantee that this method will be implemented to be efficient. For example,
+ /// it may be synchronized, or may need to run an RDBMS query.
+ ///
+ ///
+ /// Will ask the parent factory if the object cannot be found in this factory
+ /// instance.
+ ///
- /// This class is a full-fledged object factory based on object definitions
- /// that is usable straight out of the box.
- ///
- ///
- /// Can be used as an object factory in and of itself, or as a superclass
- /// for custom object factory implementations. Note that readers for
- /// specific object definition formats are typically implemented separately
- /// rather than as object factory subclasses.
- ///
- ///
- /// For an alternative implementation of the
- /// interface,
- /// have a look at the
- ///
- /// class, which manages existing object instances rather than creating new
- /// ones based on object definitions.
- ///
- ///
- /// Juergen Hoeller
- /// Rick Evans (.NET)
- ///
- [Serializable]
- public class DefaultListableObjectFactory :
- AbstractAutowireCapableObjectFactory,
- IConfigurableListableObjectFactory,
- IObjectDefinitionRegistry
- {
- #region Constructor (s) / Destructor
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- public DefaultListableObjectFactory() : this(true, null)
- {
- }
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- /// Flag specifying whether to make this object factory case sensitive or not.
- public DefaultListableObjectFactory(bool caseSensitive) : this(caseSensitive, null)
- {
- }
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- /// The parent object factory.
- public DefaultListableObjectFactory(IObjectFactory parentFactory)
- : this(true, parentFactory)
- {
- }
-
- ///
- /// Creates a new instance of the
- /// class.
- ///
- /// Flag specifying whether to make this object factory case sensitive or not.
- /// The parent object factory.
- public DefaultListableObjectFactory(bool caseSensitive, IObjectFactory parentFactory)
- : base(caseSensitive, parentFactory)
- {
- if (caseSensitive)
- {
- objectDefinitionMap = new Hashtable();
- }
- else
- {
- objectDefinitionMap = CollectionsUtil.CreateCaseInsensitiveHashtable();
- }
- }
-
- #endregion
-
- #region Properties
-
- ///
- /// Should object definitions registered under the same name as an
- /// existing object definition be allowed?
- ///
- ///
- ///
- /// If , then the new object definition will
- /// replace (override) the existing object definition. If
- /// , an exception will be thrown when
- /// an attempt is made to register an object definition under the same
- /// name as an already existing object definition.
- ///
- ///
- /// The default is .
- ///
- ///
- ///
- /// is the registration of an object definition
- /// under the same name as an existing object definition is allowed.
- ///
- public bool AllowObjectDefinitionOverriding
- {
- get { return allowObjectDefinitionOverriding; }
- set { allowObjectDefinitionOverriding = value; }
- }
-
- #endregion
-
- #region Methods
-
- ///
- /// Find object instances that match the .
- ///
- ///
- ///
- /// Called by autowiring. If a subclass cannot obtain information about object
- /// names by , a corresponding exception should be thrown.
- ///
- ///
- ///
- /// The type of the objects to look up.
- ///
- ///
- /// An of object names and object
- /// instances that match the , or
- /// if none is found.
- ///
- ///
- /// In case of errors.
- ///
- protected override IDictionary FindMatchingObjects(Type requiredType)
- {
- return ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(
- this, requiredType, true, true);
- }
-
- ///
- /// Return the names of the objects that depend on the given object.
- ///
- ///
- ///
- /// Called by the
- ///
- /// so that dependant objects are able to be disposed of first.
- ///
+ /// This class is a full-fledged object factory based on object definitions
+ /// that is usable straight out of the box.
+ ///
+ ///
+ /// Can be used as an object factory in and of itself, or as a superclass
+ /// for custom object factory implementations. Note that readers for
+ /// specific object definition formats are typically implemented separately
+ /// rather than as object factory subclasses.
+ ///
+ ///
+ /// For an alternative implementation of the
+ /// interface,
+ /// have a look at the
+ ///
+ /// class, which manages existing object instances rather than creating new
+ /// ones based on object definitions.
+ ///
+ ///
+ /// Juergen Hoeller
+ /// Rick Evans (.NET)
+ ///
+ [Serializable]
+ public class DefaultListableObjectFactory :
+ AbstractAutowireCapableObjectFactory,
+ IConfigurableListableObjectFactory,
+ IObjectDefinitionRegistry
+ {
+ #region Constructor (s) / Destructor
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ public DefaultListableObjectFactory() : this(true, null)
+ {
+ }
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ /// Flag specifying whether to make this object factory case sensitive or not.
+ public DefaultListableObjectFactory(bool caseSensitive) : this(caseSensitive, null)
+ {
+ }
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ /// The parent object factory.
+ public DefaultListableObjectFactory(IObjectFactory parentFactory)
+ : this(true, parentFactory)
+ {
+ }
+
+ ///
+ /// Creates a new instance of the
+ /// class.
+ ///
+ /// Flag specifying whether to make this object factory case sensitive or not.
+ /// The parent object factory.
+ public DefaultListableObjectFactory(bool caseSensitive, IObjectFactory parentFactory)
+ : base(caseSensitive, parentFactory)
+ {
+ if (caseSensitive)
+ {
+ objectDefinitionMap = new Hashtable();
+ }
+ else
+ {
+ objectDefinitionMap = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
+ }
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Should object definitions registered under the same name as an
+ /// existing object definition be allowed?
+ ///
+ ///
+ ///
+ /// If , then the new object definition will
+ /// replace (override) the existing object definition. If
+ /// , an exception will be thrown when
+ /// an attempt is made to register an object definition under the same
+ /// name as an already existing object definition.
+ ///
+ ///
+ /// The default is .
+ ///
+ ///
+ ///
+ /// is the registration of an object definition
+ /// under the same name as an existing object definition is allowed.
+ ///
+ public bool AllowObjectDefinitionOverriding
+ {
+ get { return allowObjectDefinitionOverriding; }
+ set { allowObjectDefinitionOverriding = value; }
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Find object instances that match the .
+ ///
+ ///
+ ///
+ /// Called by autowiring. If a subclass cannot obtain information about object
+ /// names by , a corresponding exception should be thrown.
+ ///
+ ///
+ ///
+ /// The type of the objects to look up.
+ ///
+ ///
+ /// An of object names and object
+ /// instances that match the , or
+ /// if none is found.
+ ///
+ ///
+ /// In case of errors.
+ ///
+ protected override IDictionary FindMatchingObjects(Type requiredType)
+ {
+ return ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(
+ this, requiredType, true, true);
+ }
+
+ ///
+ /// Return the names of the objects that depend on the given object.
+ ///
+ ///
+ ///
+ /// Called by the
+ ///
+ /// so that dependant objects are able to be disposed of first.
+ ///
- /// The purpose of this class is to provide a simple abstraction for creating and managing dynamic assemblies.
- ///
- ///
- /// Using this factory you can't define several modules within a single dynamic assembly - only a simple one2one relation between assembly/module is used.
- ///
- ///
- ///
- ///
+ /// The purpose of this class is to provide a simple abstraction for creating and managing dynamic assemblies.
+ ///
+ ///
+ /// Using this factory you can't define several modules within a single dynamic assembly - only a simple one2one relation between assembly/module is used.
+ ///
+ ///
+ ///
+ ///