SPRNET-1392
Introduce changes to Core container to support Code-Based Configuration
This commit is contained in:
249
src/Spring/Spring.Core/Collections/Generic/DictionarySet.cs
Normal file
249
src/Spring/Spring.Core/Collections/Generic/DictionarySet.cs
Normal file
@@ -0,0 +1,249 @@
|
||||
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Collections.Generic
|
||||
{
|
||||
/// <summary>
|
||||
/// <p><c>DictionarySet</c> is an abstract class that supports the creation of new <c>Set</c>
|
||||
/// types where the underlying data store is an <c>IDictionary</c> instance.</p>
|
||||
///
|
||||
/// <p>You can use any object that implements the <c>IDictionary</c> interface to hold set data.
|
||||
/// You can define your own, or you can use one of the objects provided in the Framework.
|
||||
/// The type of <c>IDictionary</c> you choose will affect both the performance and the behavior
|
||||
/// of the <c>Set</c> using it. </p>
|
||||
///
|
||||
/// <p>To make a <c>Set</c> typed based on your own <c>IDictionary</c>, simply derive a
|
||||
/// new class with a constructor that takes no parameters. Some <c>Set</c> implmentations
|
||||
/// cannot be defined with a default constructor. If this is the case for your class,
|
||||
/// you will need to override <c>Clone()</c> as well.</p>
|
||||
///
|
||||
/// <p>It is also standard practice that at least one of your constructors takes an <c>ICollection</c> or
|
||||
/// an <c>ISet</c> as an argument.</p>
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public abstract class DictionarySet<T> : Set<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the storage for elements in the <c>Set</c>, stored as the key-set
|
||||
/// of the <c>IDictionary</c> object. Set this object in the constructor
|
||||
/// if you create your own <c>Set</c> class.
|
||||
/// </summary>
|
||||
protected IDictionary<T, object> InternalDictionary = null;
|
||||
|
||||
private static readonly object PlaceholderObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// The placeholder object used as the value for the <c>IDictionary</c> instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// There is a single instance of this object globally, used for all <c>Sets</c>.
|
||||
/// </remarks>
|
||||
protected object Placeholder
|
||||
{
|
||||
get { return PlaceholderObject; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified element to this set if it is not already present.
|
||||
/// </summary>
|
||||
/// <param name="o">The <typeparamref name="T"/> to add to the set.</param>
|
||||
/// <returns><see langword="true" /> is the object was added, <see langword="false" /> if it was already present.</returns>
|
||||
public override bool Add(T o)
|
||||
{
|
||||
if (InternalDictionary.ContainsKey(o))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//The object we are adding is just a placeholder. The thing we are
|
||||
//really concerned with is 'o', the key.
|
||||
InternalDictionary.Add(o, PlaceholderObject);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds all the elements in the specified collection to the set if they are not already present.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects to add to the set.</param>
|
||||
/// <returns><see langword="true" /> is the set changed as a result of this operation, <see langword="false" /> if not.</returns>
|
||||
public override bool AddAll(ICollection<T> c)
|
||||
{
|
||||
bool changed = false;
|
||||
foreach (T o in c)
|
||||
{
|
||||
changed |= this.Add(o);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all objects from the set.
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
{
|
||||
InternalDictionary.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains the specified element.
|
||||
/// </summary>
|
||||
/// <param name="o">The element to look for.</param>
|
||||
/// <returns><see langword="true" /> if this set contains the specified element, <see langword="false" /> otherwise.</returns>
|
||||
public override bool Contains(T o)
|
||||
{
|
||||
return InternalDictionary.ContainsKey(o);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if the set contains all the elements in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects.</param>
|
||||
/// <returns><see langword="true" /> if the set contains all the elements in the specified collection, <see langword="false" /> otherwise.</returns>
|
||||
public override bool ContainsAll(ICollection<T> c)
|
||||
{
|
||||
foreach (T o in c)
|
||||
{
|
||||
if (!this.Contains(o))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains no elements.
|
||||
/// </summary>
|
||||
public override bool IsEmpty
|
||||
{
|
||||
get { return InternalDictionary.Count == 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified element from the set.
|
||||
/// </summary>
|
||||
/// <param name="o">The element to be removed.</param>
|
||||
/// <returns><see langword="true" /> if the set contained the specified element, <see langword="false" /> otherwise.</returns>
|
||||
public override bool Remove(T o)
|
||||
{
|
||||
bool contained = this.Contains(o);
|
||||
if (contained)
|
||||
{
|
||||
InternalDictionary.Remove(o);
|
||||
}
|
||||
return contained;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all the specified elements from this set, if they exist in this set.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of elements to remove.</param>
|
||||
/// <returns><see langword="true" /> if the set was modified as a result of this operation.</returns>
|
||||
public override bool RemoveAll(ICollection<T> c)
|
||||
{
|
||||
bool changed = false;
|
||||
foreach (T o in c)
|
||||
{
|
||||
changed |= this.Remove(o);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retains only the elements in this set that are contained in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">Collection that defines the set of elements to be retained.</param>
|
||||
/// <returns><see langword="true" /> if this set changed as a result of this operation.</returns>
|
||||
public override bool RetainAll(ICollection<T> c)
|
||||
{
|
||||
//Put data from C into a set so we can use the Contains() method.
|
||||
Set<T> cSet = new HashedSet<T>(c);
|
||||
|
||||
//We are going to build a set of elements to remove.
|
||||
Set<T> removeSet = new HashedSet<T>();
|
||||
|
||||
foreach (T o in this)
|
||||
{
|
||||
//If C does not contain O, then we need to remove O from our
|
||||
//set. We can't do this while iterating through our set, so
|
||||
//we put it into RemoveSet for later.
|
||||
if (!cSet.Contains(o))
|
||||
removeSet.Add(o);
|
||||
}
|
||||
|
||||
return this.RemoveAll(removeSet);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements in the <c>Set</c> to an array of T. The type of array needs
|
||||
/// to be compatible with the objects in the <c>Set</c>, obviously.
|
||||
/// </summary>
|
||||
/// <param name="array">An array that will be the target of the copy operation.</param>
|
||||
/// <param name="index">The zero-based index where copying will start.</param>
|
||||
public override void CopyTo(T[] array, int index)
|
||||
{
|
||||
InternalDictionary.Keys.CopyTo(array, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of elements contained in this collection.
|
||||
/// </summary>
|
||||
public override int Count
|
||||
{
|
||||
get { return InternalDictionary.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// None of the objects based on <c>DictionarySet</c> are synchronized. Use the
|
||||
/// <c>SyncRoot</c> property instead.
|
||||
/// </summary>
|
||||
public override bool IsSynchronized
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an object that can be used to synchronize the <c>Set</c> between threads.
|
||||
/// </summary>
|
||||
public override object SyncRoot
|
||||
{
|
||||
get { return ((ICollection) InternalDictionary).SyncRoot; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator for the elements in the <c>Set</c>.
|
||||
/// </summary>
|
||||
/// <returns>An <c>IEnumerator</c> over the elements in the <c>Set</c>.</returns>
|
||||
public override IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return InternalDictionary.Keys.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates wether the <c>Set</c> is read-only or not
|
||||
/// </summary>
|
||||
public override bool IsReadOnly
|
||||
{
|
||||
get { return InternalDictionary.IsReadOnly; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements in the <c>Set</c> to an array. The type of array needs
|
||||
/// to be compatible with the objects in the <c>Set</c>, obviously. Needed for
|
||||
/// non-generic ISet methods implementation
|
||||
/// </summary>
|
||||
/// <param name="array">An array that will be the target of the copy operation.</param>
|
||||
/// <param name="index">The zero-based index where copying will start.</param>
|
||||
protected override void NonGenericCopyTo(Array array, int index)
|
||||
{
|
||||
((ICollection) InternalDictionary.Keys).CopyTo(array, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/Spring/Spring.Core/Collections/Generic/HashedSet.cs
Normal file
33
src/Spring/Spring.Core/Collections/Generic/HashedSet.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Collections.Generic
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a <c>Set</c> based on a Dictionary (which is equivalent of
|
||||
/// non-genric <c>HashTable</c>) This will give the best lookup, add, and remove
|
||||
/// performance for very large data-sets, but iteration will occur in no particular order.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class HashedSet<T> : DictionarySet<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new set instance based on a Dictinary.
|
||||
/// </summary>
|
||||
public HashedSet()
|
||||
{
|
||||
InternalDictionary = new Dictionary<T, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new set instance based on a Dictinary and
|
||||
/// initializes it based on a collection of elements.
|
||||
/// </summary>
|
||||
/// <param name="initialValues">A collection of elements that defines the initial set contents.</param>
|
||||
public HashedSet(ICollection<T> initialValues) : this()
|
||||
{
|
||||
this.AddAll(initialValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
139
src/Spring/Spring.Core/Collections/Generic/ISet.cs
Normal file
139
src/Spring/Spring.Core/Collections/Generic/ISet.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Collections.Generic
|
||||
{
|
||||
/// <summary>
|
||||
/// <p>A collection that contains no duplicate elements. This interface models the mathematical
|
||||
/// <c>Set</c> abstraction.
|
||||
/// The order of elements in a set is dependant on (a)the data-structure implementation, and
|
||||
/// (b)the implementation of the various <c>Set</c> methods, and thus is not guaranteed.</p>
|
||||
///
|
||||
/// <p>None of the <c>Set</c> implementations in this library are guranteed to be thread-safe
|
||||
/// in any way unless wrapped in a <c>SynchronizedSet</c>.</p>
|
||||
///
|
||||
/// <p>The following table summarizes the binary operators that are supported by the <c>Set</c> class.</p>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Operation</term>
|
||||
/// <term>Description</term>
|
||||
/// <term>Method</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>Union (OR)</term>
|
||||
/// <term>Element included in result if it exists in either <c>A</c> OR <c>B</c>.</term>
|
||||
/// <term><c>Union()</c></term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Intersection (AND)</term>
|
||||
/// <term>Element included in result if it exists in both <c>A</c> AND <c>B</c>.</term>
|
||||
/// <term><c>InterSect()</c></term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Exclusive Or (XOR)</term>
|
||||
/// <term>Element included in result if it exists in one, but not both, of <c>A</c> and <c>B</c>.</term>
|
||||
/// <term><c>ExclusiveOr()</c></term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Minus (n/a)</term>
|
||||
/// <term>Take all the elements in <c>A</c>. Now, if any of them exist in <c>B</c>, remove
|
||||
/// them. Note that unlike the other operators, <c>A - B</c> is not the same as <c>B - A</c>.</term>
|
||||
/// <term><c>Minus()</c></term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public interface ISet<T> : ICollection<T>, IEnumerable<T>, IEnumerable, ICloneable
|
||||
{
|
||||
// Clear is declared in ICollection<T>, but not in ICollection
|
||||
// void Clear();
|
||||
|
||||
// Remove is declared in ICollection<T>, but not in ICollection
|
||||
// bool Remove(T o);
|
||||
|
||||
// Contains is declared in ICollection<T>, but not in ICollection
|
||||
// bool Contains(T o);
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "union" of the two sets, where all the elements
|
||||
/// in both sets are present. That is, the element is included if it is in either <c>a</c> or <c>b</c>.
|
||||
/// Neither this set nor the input set are modified during the operation. The return value
|
||||
/// is a <c>Clone()</c> of this set with the extra elements added in.
|
||||
/// </summary>
|
||||
/// <param name="a">A collection of elements.</param>
|
||||
/// <returns>A new <c>Set</c> containing the union of this <c>Set</c> with the specified collection.
|
||||
/// Neither of the input objects is modified by the union.</returns>
|
||||
ISet<T> Union(ISet<T> a);
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "intersection" of the two sets, where only the elements
|
||||
/// that are present in both sets remain. That is, the element is included if it exists in
|
||||
/// both sets. The <c>Intersect()</c> operation does not modify the input sets. It returns
|
||||
/// a <c>Clone()</c> of this set with the appropriate elements removed.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>The intersection of this set with <c>a</c>.</returns>
|
||||
ISet<T> Intersect(ISet<T> a);
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "minus" of set <c>b</c> from set <c>a</c>. This returns a set of all
|
||||
/// the elements in set <c>a</c>, removing the elements that are also in set <c>b</c>.
|
||||
/// The original sets are not modified during this operation. The result set is a <c>Clone()</c>
|
||||
/// of this <c>Set</c> containing the elements from the operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>A set containing the elements from this set with the elements in <c>a</c> removed.</returns>
|
||||
ISet<T> Minus(ISet<T> a);
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "exclusive-or" of the two sets, keeping only the elements that
|
||||
/// are in one of the sets, but not in both. The original sets are not modified
|
||||
/// during this operation. The result set is a <c>Clone()</c> of this set containing
|
||||
/// the elements from the exclusive-or operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>A set containing the result of <c>a ^ b</c>.</returns>
|
||||
ISet<T> ExclusiveOr(ISet<T> a);
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if the set contains all the elements in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects.</param>
|
||||
/// <returns><see langword="true" /> if the set contains all the elements in the specified collection, <see langword="false" /> otherwise.</returns>
|
||||
bool ContainsAll(ICollection<T> c);
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains no elements.
|
||||
/// </summary>
|
||||
bool IsEmpty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified element to this set if it is not already present.
|
||||
/// </summary>
|
||||
/// <param name="o">The object to add to the set.</param>
|
||||
/// <returns><see langword="true" /> is the object was added, <see langword="false" /> if it was already present.</returns>
|
||||
new bool Add(T o);
|
||||
|
||||
/// <summary>
|
||||
/// Adds all the elements in the specified collection to the set if they are not already present.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects to add to the set.</param>
|
||||
/// <returns><see langword="true" /> is the set changed as a result of this operation, <see langword="false" /> if not.</returns>
|
||||
bool AddAll(ICollection<T> c);
|
||||
|
||||
/// <summary>
|
||||
/// Remove all the specified elements from this set, if they exist in this set.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of elements to remove.</param>
|
||||
/// <returns><see langword="true" /> if the set was modified as a result of this operation.</returns>
|
||||
bool RemoveAll(ICollection<T> c);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retains only the elements in this set that are contained in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">Collection that defines the set of elements to be retained.</param>
|
||||
/// <returns><see langword="true" /> if this set changed as a result of this operation.</returns>
|
||||
bool RetainAll(ICollection<T> c);
|
||||
}
|
||||
}
|
||||
308
src/Spring/Spring.Core/Collections/Generic/ImmutableSet.cs
Normal file
308
src/Spring/Spring.Core/Collections/Generic/ImmutableSet.cs
Normal file
@@ -0,0 +1,308 @@
|
||||
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Collections.Generic
|
||||
{
|
||||
/// <summary>
|
||||
/// <p>Implements an immutable (read-only) <c>Set</c> wrapper.</p>
|
||||
/// <p>Although this is advertised as immutable, it really isn't. Anyone with access to the
|
||||
/// <c>basisSet</c> can still change the data-set. So <c>GetHashCode()</c> is not implemented
|
||||
/// for this <c>Set</c>, as is the case for all <c>Set</c> implementations in this library.
|
||||
/// This design decision was based on the efficiency of not having to <c>Clone()</c> the
|
||||
/// <c>basisSet</c> every time you wrap a mutable <c>Set</c>.</p>
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class ImmutableSet<T> : Set<T>
|
||||
{
|
||||
private const string ERROR_MESSAGE = "Object is immutable.";
|
||||
private ISet<T> mBasisSet;
|
||||
|
||||
internal ISet<T> BasisSet
|
||||
{
|
||||
get { return mBasisSet; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an immutable (read-only) <c>Set</c> wrapper.
|
||||
/// </summary>
|
||||
/// <param name="basisSet">The <c>Set</c> that is wrapped.</param>
|
||||
public ImmutableSet(ISet<T> basisSet)
|
||||
{
|
||||
mBasisSet = basisSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified element to this set if it is not already present.
|
||||
/// </summary>
|
||||
/// <param name="o">The object to add to the set.</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="NotSupportedException"> is always thrown</exception>
|
||||
public override sealed bool Add(T o)
|
||||
{
|
||||
throw new NotSupportedException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds all the elements in the specified collection to the set if they are not already present.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects to add to the set.</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="NotSupportedException"> is always thrown</exception>
|
||||
public override sealed bool AddAll(ICollection<T> c)
|
||||
{
|
||||
throw new NotSupportedException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all objects from the set.
|
||||
/// </summary>
|
||||
/// <exception cref="NotSupportedException"> is always thrown</exception>
|
||||
public override sealed void Clear()
|
||||
{
|
||||
throw new NotSupportedException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains the specified element.
|
||||
/// </summary>
|
||||
/// <param name="o">The element to look for.</param>
|
||||
/// <returns><see langword="true" /> if this set contains the specified element, <see langword="false" /> otherwise.</returns>
|
||||
public override sealed bool Contains(T o)
|
||||
{
|
||||
return mBasisSet.Contains(o);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if the set contains all the elements in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects.</param>
|
||||
/// <returns><see langword="true" /> if the set contains all the elements in the specified collection, <see langword="false" /> otherwise.</returns>
|
||||
public override sealed bool ContainsAll(ICollection<T> c)
|
||||
{
|
||||
return mBasisSet.ContainsAll(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains no elements.
|
||||
/// </summary>
|
||||
public override sealed bool IsEmpty
|
||||
{
|
||||
get { return mBasisSet.IsEmpty; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified element from the set.
|
||||
/// </summary>
|
||||
/// <param name="o">The element to be removed.</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="NotSupportedException"> is always thrown</exception>
|
||||
public override sealed bool Remove(T o)
|
||||
{
|
||||
throw new NotSupportedException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all the specified elements from this set, if they exist in this set.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of elements to remove.</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="NotSupportedException"> is always thrown</exception>
|
||||
public override sealed bool RemoveAll(ICollection<T> c)
|
||||
{
|
||||
throw new NotSupportedException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retains only the elements in this set that are contained in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">Collection that defines the set of elements to be retained.</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="NotSupportedException"> is always thrown</exception>
|
||||
public override sealed bool RetainAll(ICollection<T> c)
|
||||
{
|
||||
throw new NotSupportedException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements in the <c>Set</c> to an array of T. The type of array needs
|
||||
/// to be compatible with the objects in the <c>Set</c>, obviously.
|
||||
/// </summary>
|
||||
/// <param name="array">An array that will be the target of the copy operation.</param>
|
||||
/// <param name="index">The zero-based index where copying will start.</param>
|
||||
public override sealed void CopyTo(T[] array, int index)
|
||||
{
|
||||
mBasisSet.CopyTo(array, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of elements contained in this collection.
|
||||
/// </summary>
|
||||
public override sealed int Count
|
||||
{
|
||||
get { return mBasisSet.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an object that can be used to synchronize use of the <c>Set</c> across threads.
|
||||
/// </summary>
|
||||
public override sealed bool IsSynchronized
|
||||
{
|
||||
get { return ((ICollection) mBasisSet).IsSynchronized; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an object that can be used to synchronize the <c>Set</c> between threads.
|
||||
/// </summary>
|
||||
public override sealed object SyncRoot
|
||||
{
|
||||
get { return ((ICollection) mBasisSet).SyncRoot; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator for the elements in the <c>Set</c>.
|
||||
/// </summary>
|
||||
/// <returns>An <c>IEnumerator</c> over the elements in the <c>Set</c>.</returns>
|
||||
public override sealed IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return mBasisSet.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clone of the <c>Set</c> instance.
|
||||
/// </summary>
|
||||
/// <returns>A clone of this object.</returns>
|
||||
public override sealed object Clone()
|
||||
{
|
||||
return new ImmutableSet<T>(mBasisSet);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "union" of the two sets, where all the elements
|
||||
/// in both sets are present. That is, the element is included if it is in either <c>a</c> or <c>b</c>.
|
||||
/// Neither this set nor the input set are modified during the operation. The return value
|
||||
/// is a <c>Clone()</c> of this set with the extra elements added in.
|
||||
/// </summary>
|
||||
/// <param name="a">A collection of elements.</param>
|
||||
/// <returns>A new <c>Set</c> containing the union of this <c>Set</c> with the specified collection.
|
||||
/// Neither of the input objects is modified by the union.</returns>
|
||||
public override sealed ISet<T> Union(ISet<T> a)
|
||||
{
|
||||
ISet<T> m = GetUltimateBasisSet();
|
||||
return new ImmutableSet<T>(m.Union(a));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "intersection" of the two sets, where only the elements
|
||||
/// that are present in both sets remain. That is, the element is included if it exists in
|
||||
/// both sets. The <c>Intersect()</c> operation does not modify the input sets. It returns
|
||||
/// a <c>Clone()</c> of this set with the appropriate elements removed.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>The intersection of this set with <c>a</c>.</returns>
|
||||
public override sealed ISet<T> Intersect(ISet<T> a)
|
||||
{
|
||||
ISet<T> m = GetUltimateBasisSet();
|
||||
return new ImmutableSet<T>(m.Intersect(a));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "minus" of set <c>b</c> from set <c>a</c>. This returns a set of all
|
||||
/// the elements in set <c>a</c>, removing the elements that are also in set <c>b</c>.
|
||||
/// The original sets are not modified during this operation. The result set is a <c>Clone()</c>
|
||||
/// of this <c>Set</c> containing the elements from the operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>A set containing the elements from this set with the elements in <c>a</c> removed.</returns>
|
||||
public override sealed ISet<T> Minus(ISet<T> a)
|
||||
{
|
||||
ISet<T> m = GetUltimateBasisSet();
|
||||
return new ImmutableSet<T>(m.Minus(a));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "exclusive-or" of the two sets, keeping only the elements that
|
||||
/// are in one of the sets, but not in both. The original sets are not modified
|
||||
/// during this operation. The result set is a <c>Clone()</c> of this set containing
|
||||
/// the elements from the exclusive-or operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>A set containing the result of <c>a ^ b</c>.</returns>
|
||||
public override sealed ISet<T> ExclusiveOr(ISet<T> a)
|
||||
{
|
||||
ISet<T> m = GetUltimateBasisSet();
|
||||
return new ImmutableSet<T>(m.ExclusiveOr(a));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the given instance is read-only
|
||||
/// </summary>
|
||||
public override sealed bool IsReadOnly
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs CopyTo when called trhough non-generic ISet (ICollection) interface
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="index"></param>
|
||||
protected override void NonGenericCopyTo(Array array, int index)
|
||||
{
|
||||
((ICollection) this.BasisSet).CopyTo(array, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs Union when called trhough non-generic ISet interface
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
protected override sealed ISet NonGenericUnion(ISet a)
|
||||
{
|
||||
ISet<T> m = GetUltimateBasisSet();
|
||||
return new ImmutableSet(((ISet) m).Union(a));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs Minus when called trhough non-generic ISet interface
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
protected override sealed ISet NonGenericMinus(ISet a)
|
||||
{
|
||||
ISet<T> m = GetUltimateBasisSet();
|
||||
return new ImmutableSet(((ISet) m).Minus(a));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs Intersect when called trhough non-generic ISet interface
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
protected override sealed ISet NonGenericIntersect(ISet a)
|
||||
{
|
||||
ISet<T> m = GetUltimateBasisSet();
|
||||
return new ImmutableSet(((ISet) m).Intersect(a));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs ExclusiveOr when called trhough non-generic ISet interface
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
protected override sealed ISet NonGenericExclusiveOr(ISet a)
|
||||
{
|
||||
ISet<T> m = GetUltimateBasisSet();
|
||||
return new ImmutableSet(((ISet) m).ExclusiveOr(a));
|
||||
}
|
||||
|
||||
private ISet<T> GetUltimateBasisSet()
|
||||
{
|
||||
ISet<T> m = this.mBasisSet;
|
||||
while (m is ImmutableSet<T>)
|
||||
m = ((ImmutableSet<T>) m).mBasisSet;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/Spring/Spring.Core/Collections/Generic/OrderedSet.cs
Normal file
30
src/Spring/Spring.Core/Collections/Generic/OrderedSet.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Collections.Generic
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements an ordered <c>Set</c> based on a dictionary.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class OrderedSet<T> : DictionarySet<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OrderedSet{T}" /> class.
|
||||
/// </summary>
|
||||
public OrderedSet()
|
||||
{
|
||||
InternalDictionary = new Dictionary<T, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OrderedSet{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initialValues">A collection of elements that defines the initial set contents.</param>
|
||||
public OrderedSet(ICollection<T> initialValues)
|
||||
: this()
|
||||
{
|
||||
AddAll(initialValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
561
src/Spring/Spring.Core/Collections/Generic/Set.cs
Normal file
561
src/Spring/Spring.Core/Collections/Generic/Set.cs
Normal file
@@ -0,0 +1,561 @@
|
||||
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Collections.Generic
|
||||
{
|
||||
/// <summary><p>A collection that contains no duplicate elements. This class models the mathematical
|
||||
/// <c>Set</c> abstraction, and is the base class for all other <c>Set</c> implementations.
|
||||
/// The order of elements in a set is dependant on (a)the data-structure implementation, and
|
||||
/// (b)the implementation of the various <c>Set</c> methods, and thus is not guaranteed.</p>
|
||||
///
|
||||
/// <p>None of the <c>Set</c> implementations in this library are guranteed to be thread-safe
|
||||
/// in any way unless wrapped in a <c>SynchronizedSet</c>.</p>
|
||||
///
|
||||
/// <p>The following table summarizes the binary operators that are supported by the <c>Set</c> class.</p>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Operation</term>
|
||||
/// <term>Description</term>
|
||||
/// <term>Method</term>
|
||||
/// <term>Operator</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>Union (OR)</term>
|
||||
/// <term>Element included in result if it exists in either <c>A</c> OR <c>B</c>.</term>
|
||||
/// <term><c>Union()</c></term>
|
||||
/// <term><c>|</c></term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Intersection (AND)</term>
|
||||
/// <term>Element included in result if it exists in both <c>A</c> AND <c>B</c>.</term>
|
||||
/// <term><c>InterSect()</c></term>
|
||||
/// <term><c>&</c></term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Exclusive Or (XOR)</term>
|
||||
/// <term>Element included in result if it exists in one, but not both, of <c>A</c> and <c>B</c>.</term>
|
||||
/// <term><c>ExclusiveOr()</c></term>
|
||||
/// <term><c>^</c></term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Minus (n/a)</term>
|
||||
/// <term>Take all the elements in <c>A</c>. Now, if any of them exist in <c>B</c>, remove
|
||||
/// them. Note that unlike the other operators, <c>A - B</c> is not the same as <c>B - A</c>.</term>
|
||||
/// <term><c>Minus()</c></term>
|
||||
/// <term><c>-</c></term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public abstract class Set<T> : ISet<T>, ICollection<T>, IEnumerable<T>,
|
||||
ISet, ICollection, IEnumerable, ICloneable
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs a "union" of the two sets, where all the elements
|
||||
/// in both sets are present. That is, the element is included if it is in either <c>a</c> or <c>b</c>.
|
||||
/// Neither this set nor the input set are modified during the operation. The return value
|
||||
/// is a <c>Clone()</c> of this set with the extra elements added in.
|
||||
/// </summary>
|
||||
/// <param name="a">A collection of elements.</param>
|
||||
/// <returns>A new <c>Set</c> containing the union of this <c>Set</c> with the specified collection.
|
||||
/// Neither of the input objects is modified by the union.</returns>
|
||||
public virtual ISet<T> Union(ISet<T> a)
|
||||
{
|
||||
ISet<T> resultSet = (ISet<T>) this.Clone();
|
||||
if (a != null)
|
||||
{
|
||||
resultSet.AddAll(a);
|
||||
}
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "union" of two sets, where all the elements
|
||||
/// in both are present. That is, the element is included if it is in either <c>a</c> or <c>b</c>.
|
||||
/// The return value is a <c>Clone()</c> of one of the sets (<c>a</c> if it is not <see langword="null" />) with elements of the other set
|
||||
/// added in. Neither of the input sets is modified by the operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <param name="b">A set of elements.</param>
|
||||
/// <returns>A set containing the union of the input sets. <see langword="null" /> if both sets are <see langword="null" />.</returns>
|
||||
public static ISet<T> Union(ISet<T> a, ISet<T> b)
|
||||
{
|
||||
if (a == null && b == null)
|
||||
return null;
|
||||
else if (a == null)
|
||||
return (ISet<T>) b.Clone();
|
||||
else if (b == null)
|
||||
return (ISet<T>) a.Clone();
|
||||
else
|
||||
return a.Union(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "union" of two sets, where all the elements
|
||||
/// in both are present. That is, the element is included if it is in either <c>a</c> or <c>b</c>.
|
||||
/// The return value is a <c>Clone()</c> of one of the sets (<c>a</c> if it is not <see langword="null" />) with elements of the other set
|
||||
/// added in. Neither of the input sets is modified by the operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <param name="b">A set of elements.</param>
|
||||
/// <returns>A set containing the union of the input sets. <see langword="null" /> if both sets are <see langword="null" />.</returns>
|
||||
public static Set<T> operator |(Set<T> a, Set<T> b)
|
||||
{
|
||||
return (Set<T>) Union(a, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "intersection" of the two sets, where only the elements
|
||||
/// that are present in both sets remain. That is, the element is included if it exists in
|
||||
/// both sets. The <c>Intersect()</c> operation does not modify the input sets. It returns
|
||||
/// a <c>Clone()</c> of this set with the appropriate elements removed.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>The intersection of this set with <c>a</c>.</returns>
|
||||
public virtual ISet<T> Intersect(ISet<T> a)
|
||||
{
|
||||
ISet<T> resultSet = (ISet<T>) this.Clone();
|
||||
if (a != null)
|
||||
resultSet.RetainAll(a);
|
||||
else
|
||||
resultSet.Clear();
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "intersection" of the two sets, where only the elements
|
||||
/// that are present in both sets remain. That is, the element is included only if it exists in
|
||||
/// both <c>a</c> and <c>b</c>. Neither input object is modified by the operation.
|
||||
/// The result object is a <c>Clone()</c> of one of the input objects (<c>a</c> if it is not <see langword="null" />) containing the
|
||||
/// elements from the intersect operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <param name="b">A set of elements.</param>
|
||||
/// <returns>The intersection of the two input sets. <see langword="null" /> if both sets are <see langword="null" />.</returns>
|
||||
public static ISet<T> Intersect(ISet<T> a, ISet<T> b)
|
||||
{
|
||||
if (a == null && b == null)
|
||||
return null;
|
||||
else if (a == null)
|
||||
{
|
||||
return b.Intersect(a);
|
||||
}
|
||||
else
|
||||
return a.Intersect(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "intersection" of the two sets, where only the elements
|
||||
/// that are present in both sets remain. That is, the element is included only if it exists in
|
||||
/// both <c>a</c> and <c>b</c>. Neither input object is modified by the operation.
|
||||
/// The result object is a <c>Clone()</c> of one of the input objects (<c>a</c> if it is not <see langword="null" />) containing the
|
||||
/// elements from the intersect operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <param name="b">A set of elements.</param>
|
||||
/// <returns>The intersection of the two input sets. <see langword="null" /> if both sets are <see langword="null" />.</returns>
|
||||
public static Set<T> operator &(Set<T> a, Set<T> b)
|
||||
{
|
||||
return (Set<T>) Intersect(a, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "minus" of set <c>b</c> from set <c>a</c>. This returns a set of all
|
||||
/// the elements in set <c>a</c>, removing the elements that are also in set <c>b</c>.
|
||||
/// The original sets are not modified during this operation. The result set is a <c>Clone()</c>
|
||||
/// of this <c>Set</c> containing the elements from the operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>A set containing the elements from this set with the elements in <c>a</c> removed.</returns>
|
||||
public virtual ISet<T> Minus(ISet<T> a)
|
||||
{
|
||||
ISet<T> resultSet = (ISet<T>) this.Clone();
|
||||
if (a != null)
|
||||
resultSet.RemoveAll(a);
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "minus" of set <c>b</c> from set <c>a</c>. This returns a set of all
|
||||
/// the elements in set <c>a</c>, removing the elements that are also in set <c>b</c>.
|
||||
/// The original sets are not modified during this operation. The result set is a <c>Clone()</c>
|
||||
/// of set <c>a</c> containing the elements from the operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <param name="b">A set of elements.</param>
|
||||
/// <returns>A set containing <c>A - B</c> elements. <see langword="null" /> if <c>a</c> is <see langword="null" />.</returns>
|
||||
public static ISet<T> Minus(ISet<T> a, ISet<T> b)
|
||||
{
|
||||
if (a == null)
|
||||
return null;
|
||||
else
|
||||
return a.Minus(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a "minus" of set <c>b</c> from set <c>a</c>. This returns a set of all
|
||||
/// the elements in set <c>a</c>, removing the elements that are also in set <c>b</c>.
|
||||
/// The original sets are not modified during this operation. The result set is a <c>Clone()</c>
|
||||
/// of set <c>a</c> containing the elements from the operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <param name="b">A set of elements.</param>
|
||||
/// <returns>A set containing <c>A - B</c> elements. <see langword="null" /> if <c>a</c> is <see langword="null" />.</returns>
|
||||
public static Set<T> operator -(Set<T> a, Set<T> b)
|
||||
{
|
||||
return (Set<T>) Minus(a, b);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "exclusive-or" of the two sets, keeping only the elements that
|
||||
/// are in one of the sets, but not in both. The original sets are not modified
|
||||
/// during this operation. The result set is a <c>Clone()</c> of this set containing
|
||||
/// the elements from the exclusive-or operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <returns>A set containing the result of <c>a ^ b</c>.</returns>
|
||||
public virtual ISet<T> ExclusiveOr(ISet<T> a)
|
||||
{
|
||||
ISet<T> resultSet = (ISet<T>) this.Clone();
|
||||
foreach (T element in a)
|
||||
{
|
||||
if (resultSet.Contains(element))
|
||||
resultSet.Remove(element);
|
||||
else
|
||||
resultSet.Add(element);
|
||||
}
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "exclusive-or" of the two sets, keeping only the elements that
|
||||
/// are in one of the sets, but not in both. The original sets are not modified
|
||||
/// during this operation. The result set is a <c>Clone()</c> of one of the sets
|
||||
/// (<c>a</c> if it is not <see langword="null" />) containing
|
||||
/// the elements from the exclusive-or operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <param name="b">A set of elements.</param>
|
||||
/// <returns>A set containing the result of <c>a ^ b</c>. <see langword="null" /> if both sets are <see langword="null" />.</returns>
|
||||
public static ISet<T> ExclusiveOr(ISet<T> a, ISet<T> b)
|
||||
{
|
||||
if (a == null && b == null)
|
||||
return null;
|
||||
else if (a == null)
|
||||
return (ISet<T>) b.Clone();
|
||||
else if (b == null)
|
||||
return (ISet<T>) a.Clone();
|
||||
else
|
||||
return a.ExclusiveOr(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an "exclusive-or" of the two sets, keeping only the elements that
|
||||
/// are in one of the sets, but not in both. The original sets are not modified
|
||||
/// during this operation. The result set is a <c>Clone()</c> of one of the sets
|
||||
/// (<c>a</c> if it is not <see langword="null" />) containing
|
||||
/// the elements from the exclusive-or operation.
|
||||
/// </summary>
|
||||
/// <param name="a">A set of elements.</param>
|
||||
/// <param name="b">A set of elements.</param>
|
||||
/// <returns>A set containing the result of <c>a ^ b</c>. <see langword="null" /> if both sets are <see langword="null" />.</returns>
|
||||
public static Set<T> operator ^(Set<T> a, Set<T> b)
|
||||
{
|
||||
return (Set<T>) ExclusiveOr(a, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified element to this set if it is not already present.
|
||||
/// </summary>
|
||||
/// <param name="o">The object to add to the set.</param>
|
||||
/// <returns><see langword="true" /> is the object was added, <see langword="false" /> if it was already present.</returns>
|
||||
public abstract bool Add(T o);
|
||||
|
||||
/// <summary>
|
||||
/// Adds all the elements in the specified collection to the set if they are not already present.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects to add to the set.</param>
|
||||
/// <returns><see langword="true" /> is the set changed as a result of this operation, <see langword="false" /> if not.</returns>
|
||||
public abstract bool AddAll(ICollection<T> c);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all objects from the set.
|
||||
/// </summary>
|
||||
public abstract void Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains the specified element.
|
||||
/// </summary>
|
||||
/// <param name="o">The element to look for.</param>
|
||||
/// <returns><see langword="true" /> if this set contains the specified element, <see langword="false" /> otherwise.</returns>
|
||||
public abstract bool Contains(T o);
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if the set contains all the elements in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects.</param>
|
||||
/// <returns><see langword="true" /> if the set contains all the elements in the specified collection, <see langword="false" /> otherwise.</returns>
|
||||
public abstract bool ContainsAll(ICollection<T> c);
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains no elements.
|
||||
/// </summary>
|
||||
public abstract bool IsEmpty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified element from the set.
|
||||
/// </summary>
|
||||
/// <param name="o">The element to be removed.</param>
|
||||
/// <returns><see langword="true" /> if the set contained the specified element, <see langword="false" /> otherwise.</returns>
|
||||
public abstract bool Remove(T o);
|
||||
|
||||
/// <summary>
|
||||
/// Remove all the specified elements from this set, if they exist in this set.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of elements to remove.</param>
|
||||
/// <returns><see langword="true" /> if the set was modified as a result of this operation.</returns>
|
||||
public abstract bool RemoveAll(ICollection<T> c);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retains only the elements in this set that are contained in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">Collection that defines the set of elements to be retained.</param>
|
||||
/// <returns><see langword="true" /> if this set changed as a result of this operation.</returns>
|
||||
public abstract bool RetainAll(ICollection<T> c);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clone of the <c>Set</c> instance. This will work for derived <c>Set</c>
|
||||
/// classes if the derived class implements a constructor that takes no arguments.
|
||||
/// </summary>
|
||||
/// <returns>A clone of this object.</returns>
|
||||
public virtual object Clone()
|
||||
{
|
||||
Set<T> newSet = (Set<T>) Activator.CreateInstance(this.GetType());
|
||||
newSet.AddAll(this);
|
||||
return newSet;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements in the <c>Set</c> to an array. The type of array needs
|
||||
/// to be compatible with the objects in the <c>Set</c>, obviously.
|
||||
/// </summary>
|
||||
/// <param name="array">An array that will be the target of the copy operation.</param>
|
||||
/// <param name="index">The zero-based index where copying will start.</param>
|
||||
public abstract void CopyTo(T[] array, int index);
|
||||
|
||||
/// <summary>
|
||||
/// The number of elements currently contained in this collection.
|
||||
/// </summary>
|
||||
public abstract int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if the <c>Set</c> is synchronized across threads. Note that
|
||||
/// enumeration is inherently not thread-safe. Use the <c>SyncRoot</c> to lock the
|
||||
/// object during enumeration.
|
||||
/// </summary>
|
||||
public abstract bool IsSynchronized { get; }
|
||||
|
||||
/// <summary>
|
||||
/// An object that can be used to synchronize this collection to make it thread-safe.
|
||||
/// When implementing this, if your object uses a base object, like an <c>IDictionary</c>,
|
||||
/// or anything that has a <c>SyncRoot</c>, return that object instead of "<c>this</c>".
|
||||
/// </summary>
|
||||
public abstract object SyncRoot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator for the elements in the <c>Set</c>.
|
||||
/// </summary>
|
||||
/// <returns>An <c>IEnumerator</c> over the elements in the <c>Set</c>.</returns>
|
||||
public abstract IEnumerator<T> GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the given instance is read-only or not
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the ISet is read-only; otherwise, <see langword="false" />.
|
||||
/// In the default implementation of Set, this property always returns false.
|
||||
/// </value>
|
||||
public virtual bool IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
void ICollection<T>.Add(T item)
|
||||
{
|
||||
this.Add(item);
|
||||
}
|
||||
|
||||
#region Protected helpers
|
||||
|
||||
/// <summary>
|
||||
/// Performs CopyTo when called trhough non-generic ISet (ICollection) interface
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="index"></param>
|
||||
protected abstract void NonGenericCopyTo(Array array, int index);
|
||||
|
||||
/// <summary>
|
||||
/// Performs Union when called trhough non-generic ISet interface
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual ISet NonGenericUnion(ISet a)
|
||||
{
|
||||
ISet resultSet = (ISet) this.Clone();
|
||||
if (a != null)
|
||||
resultSet.AddAll(a);
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs Minus when called trhough non-generic ISet interface
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual ISet NonGenericMinus(ISet a)
|
||||
{
|
||||
ISet resultSet = (ISet) this.Clone();
|
||||
if (a != null)
|
||||
resultSet.RemoveAll(a);
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs Intersect when called trhough non-generic ISet interface
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual ISet NonGenericIntersect(ISet a)
|
||||
{
|
||||
ISet resultSet = (ISet) this.Clone();
|
||||
if (a != null)
|
||||
resultSet.RetainAll(a);
|
||||
else
|
||||
resultSet.Clear();
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs ExclusiveOr when called trhough non-generic ISet interface
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual ISet NonGenericExclusiveOr(ISet a)
|
||||
{
|
||||
ISet resultSet = (ISet) this.Clone();
|
||||
foreach (object element in a)
|
||||
{
|
||||
if (resultSet.Contains(element))
|
||||
resultSet.Remove(element);
|
||||
else
|
||||
resultSet.Add(element);
|
||||
}
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
#endregion Protected helpers
|
||||
|
||||
#region ISet implementation
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
this.NonGenericCopyTo(array, index);
|
||||
}
|
||||
|
||||
ISet ISet.Union(ISet a)
|
||||
{
|
||||
return this.NonGenericUnion(a);
|
||||
}
|
||||
|
||||
ISet ISet.Intersect(ISet a)
|
||||
{
|
||||
return NonGenericIntersect(a);
|
||||
}
|
||||
|
||||
ISet ISet.Minus(ISet a)
|
||||
{
|
||||
return NonGenericMinus(a);
|
||||
}
|
||||
|
||||
ISet ISet.ExclusiveOr(ISet a)
|
||||
{
|
||||
return NonGenericExclusiveOr(a);
|
||||
}
|
||||
|
||||
bool ISet.Contains(object o)
|
||||
{
|
||||
if (o is T)
|
||||
return this.Contains((T) o);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ISet.ContainsAll(ICollection c)
|
||||
{
|
||||
ICollection<T> col = new List<T>(c.Count);
|
||||
foreach (object o in c)
|
||||
{
|
||||
if (o is T)
|
||||
col.Add((T) o);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return this.ContainsAll(col);
|
||||
}
|
||||
|
||||
bool ISet.Add(object o)
|
||||
{
|
||||
return this.Add((T) o);
|
||||
}
|
||||
|
||||
bool ISet.AddAll(ICollection c)
|
||||
{
|
||||
bool changed = false;
|
||||
foreach (T obj in c)
|
||||
changed |= this.Add(obj);
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ISet.Remove(object o)
|
||||
{
|
||||
if (o is T)
|
||||
return this.Remove((T) o);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ISet.RemoveAll(ICollection c)
|
||||
{
|
||||
ICollection<T> col = new List<T>(c.Count);
|
||||
foreach (object o in c)
|
||||
{
|
||||
if (o is T)
|
||||
col.Add((T) o);
|
||||
}
|
||||
return this.RemoveAll(col);
|
||||
}
|
||||
|
||||
bool ISet.RetainAll(ICollection c)
|
||||
{
|
||||
ICollection<T> col = new List<T>(c.Count);
|
||||
foreach (object o in c)
|
||||
{
|
||||
if (o is T)
|
||||
col.Add((T) o);
|
||||
}
|
||||
return this.RetainAll(col);
|
||||
}
|
||||
|
||||
#endregion ISet implementation
|
||||
}
|
||||
}
|
||||
69
src/Spring/Spring.Core/Collections/Generic/SortedSet.cs
Normal file
69
src/Spring/Spring.Core/Collections/Generic/SortedSet.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Collections.Generic
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a <c>Set</c> based on a sorted tree. This gives good performance for operations on very
|
||||
/// large data-sets, though not as good - asymptotically - as a <c>HashedSet</c>. However, iteration
|
||||
/// occurs in order. Elements that you put into this type of collection must implement <c>IComparable</c>,
|
||||
/// and they must actually be comparable. You can't mix <c>string</c> and <c>int</c> values, for example.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SortedSet<T> : DictionarySet<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new set instance based on a sorted tree.
|
||||
/// </summary>
|
||||
public SortedSet()
|
||||
{
|
||||
InternalDictionary = new SortedDictionary<T, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new set instance based on a sorted tree.
|
||||
/// </summary>
|
||||
/// <param name="comparer">The <see cref="IComparer<T>"/> to use for sorting.</param>
|
||||
public SortedSet(IComparer<T> comparer)
|
||||
{
|
||||
InternalDictionary = new SortedList<T, object>(comparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new set instance based on a sorted tree and
|
||||
/// initializes it based on a collection of elements.
|
||||
/// </summary>
|
||||
/// <param name="initialValues">A collection of elements that defines the initial set contents.</param>
|
||||
public SortedSet(ICollection<T> initialValues)
|
||||
: this()
|
||||
{
|
||||
this.AddAll(initialValues);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new set instance based on a sorted tree and
|
||||
/// initializes it based on a collection of elements.
|
||||
/// </summary>
|
||||
/// <param name="initialValues">A collection of elements that defines the initial set contents.</param>
|
||||
public SortedSet(ICollection initialValues)
|
||||
: this()
|
||||
{
|
||||
((ISet) this).AddAll(initialValues);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new set instance based on a sorted tree and
|
||||
/// initializes it based on a collection of elements.
|
||||
/// </summary>
|
||||
/// <param name="initialValues">A collection of elements that defines the initial set contents.</param>
|
||||
/// <param name="comparer">The <see cref="IComparer<T>"/> to use for sorting.</param>
|
||||
public SortedSet(ICollection<T> initialValues, IComparer<T> comparer)
|
||||
: this(comparer)
|
||||
{
|
||||
this.AddAll(initialValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
262
src/Spring/Spring.Core/Collections/Generic/SynchronizedSet.cs
Normal file
262
src/Spring/Spring.Core/Collections/Generic/SynchronizedSet.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spring.Collections.Generic
|
||||
{
|
||||
/// <summary>
|
||||
/// <p>Implements a thread-safe <c>Set</c> wrapper. The implementation is extremely conservative,
|
||||
/// serializing critical sections to prevent possible deadlocks, and locking on everything.
|
||||
/// The one exception is for enumeration, which is inherently not thread-safe. For this, you
|
||||
/// have to <c>lock</c> the <c>SyncRoot</c> object for the duration of the enumeration.</p>
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class SynchronizedSet<T> : Set<T>
|
||||
{
|
||||
private ISet<T> mBasisSet;
|
||||
private object mSyncRoot;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a thread-safe <c>Set</c> wrapper.
|
||||
/// </summary>
|
||||
/// <param name="basisSet">The <c>Set</c> object that this object will wrap.</param>
|
||||
public SynchronizedSet(ISet<T> basisSet)
|
||||
{
|
||||
mBasisSet = basisSet;
|
||||
mSyncRoot = ((ICollection) basisSet).SyncRoot;
|
||||
if (mSyncRoot == null)
|
||||
throw new NullReferenceException("The Set you specified returned a null SyncRoot.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified element to this set if it is not already present.
|
||||
/// </summary>
|
||||
/// <param name="o">The object to add to the set.</param>
|
||||
/// <returns><see langword="true" /> is the object was added, <see langword="false" /> if it was already present.</returns>
|
||||
public override sealed bool Add(T o)
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.Add(o);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds all the elements in the specified collection to the set if they are not already present.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects to add to the set.</param>
|
||||
/// <returns><see langword="true" /> is the set changed as a result of this operation, <see langword="false" /> if not.</returns>
|
||||
public override sealed bool AddAll(ICollection<T> c)
|
||||
{
|
||||
Set<T> temp;
|
||||
lock (((ICollection) c).SyncRoot)
|
||||
{
|
||||
temp = new HashedSet<T>(c);
|
||||
}
|
||||
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.AddAll(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all objects from the set.
|
||||
/// </summary>
|
||||
public override sealed void Clear()
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
mBasisSet.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains the specified element.
|
||||
/// </summary>
|
||||
/// <param name="o">The element to look for.</param>
|
||||
/// <returns><see langword="true" /> if this set contains the specified element, <see langword="false" /> otherwise.</returns>
|
||||
public override sealed bool Contains(T o)
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.Contains(o);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if the set contains all the elements in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of objects.</param>
|
||||
/// <returns><see langword="true" /> if the set contains all the elements in the specified collection, <see langword="false" /> otherwise.</returns>
|
||||
public override sealed bool ContainsAll(ICollection<T> c)
|
||||
{
|
||||
Set<T> temp;
|
||||
lock (((ICollection) c).SyncRoot)
|
||||
{
|
||||
temp = new HashedSet<T>(c);
|
||||
}
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.ContainsAll(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" /> if this set contains no elements.
|
||||
/// </summary>
|
||||
public override sealed bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.IsEmpty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified element from the set.
|
||||
/// </summary>
|
||||
/// <param name="o">The element to be removed.</param>
|
||||
/// <returns><see langword="true" /> if the set contained the specified element, <see langword="false" /> otherwise.</returns>
|
||||
public override sealed bool Remove(T o)
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.Remove(o);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all the specified elements from this set, if they exist in this set.
|
||||
/// </summary>
|
||||
/// <param name="c">A collection of elements to remove.</param>
|
||||
/// <returns><see langword="true" /> if the set was modified as a result of this operation.</returns>
|
||||
public override sealed bool RemoveAll(ICollection<T> c)
|
||||
{
|
||||
Set<T> temp;
|
||||
lock (((ICollection) c).SyncRoot)
|
||||
{
|
||||
temp = new HashedSet<T>(c);
|
||||
}
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.RemoveAll(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retains only the elements in this set that are contained in the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="c">Collection that defines the set of elements to be retained.</param>
|
||||
/// <returns><see langword="true" /> if this set changed as a result of this operation.</returns>
|
||||
public override sealed bool RetainAll(ICollection<T> c)
|
||||
{
|
||||
Set<T> temp;
|
||||
lock (((ICollection) c).SyncRoot)
|
||||
{
|
||||
temp = new HashedSet<T>(c);
|
||||
}
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.RetainAll(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements in the <c>Set</c> to an array. The type of array needs
|
||||
/// to be compatible with the objects in the <c>Set</c>, obviously.
|
||||
/// </summary>
|
||||
/// <param name="array">An array that will be the target of the copy operation.</param>
|
||||
/// <param name="index">The zero-based index where copying will start.</param>
|
||||
public override sealed void CopyTo(T[] array, int index)
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
mBasisSet.CopyTo(array, index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of elements contained in this collection.
|
||||
/// </summary>
|
||||
public override sealed int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true" />, indicating that this object is thread-safe. The exception to this
|
||||
/// is enumeration, which is inherently not thread-safe. Use the <c>SyncRoot</c> object to
|
||||
/// lock this object for the entire duration of the enumeration.
|
||||
/// </summary>
|
||||
public override sealed bool IsSynchronized
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an object that can be used to synchronize the <c>Set</c> between threads.
|
||||
/// </summary>
|
||||
public override sealed object SyncRoot
|
||||
{
|
||||
get { return mSyncRoot; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration is, by definition, not thread-safe. Use a <c>lock</c> on the <c>SyncRoot</c>
|
||||
/// to synchronize the entire enumeration process.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override sealed IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return mBasisSet.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clone of the <c>Set</c> instance.
|
||||
/// </summary>
|
||||
/// <returns>A clone of this object.</returns>
|
||||
public override object Clone()
|
||||
{
|
||||
return new SynchronizedSet((ISet) mBasisSet.Clone());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether given instace is read-only or not
|
||||
/// </summary>
|
||||
public override bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
return mBasisSet.IsReadOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs CopyTo when called trhough non-generic ISet (ICollection) interface
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="index"></param>
|
||||
protected override void NonGenericCopyTo(Array array, int index)
|
||||
{
|
||||
lock (mSyncRoot)
|
||||
{
|
||||
((ICollection) this.mBasisSet).CopyTo(array, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,7 +406,7 @@ namespace Spring.Context.Support
|
||||
if (exceptions.HasExceptions)
|
||||
{
|
||||
Delegate target = ContextEvent.GetInvocationList()[0];
|
||||
Exception exception = (Exception) exceptions[target];
|
||||
Exception exception = (Exception)exceptions[target];
|
||||
throw new ApplicationContextException(string.Format("An unhandled exception occured during processing application event {0} in handler {1}", e.GetType(), target.Method), exception);
|
||||
}
|
||||
}
|
||||
@@ -487,33 +487,92 @@ namespace Spring.Context.Support
|
||||
/// </note>
|
||||
/// </remarks>
|
||||
/// <exception cref="ObjectsException">In the case of errors.</exception>
|
||||
private void InvokeObjectFactoryPostProcessors()
|
||||
private void InvokeObjectFactoryPostProcessors(IConfigurableListableObjectFactory objectFactory)
|
||||
{
|
||||
// Do NOT include IFactoryObjects; they (typically) need to be instantiated
|
||||
// to determine the Type of object that they create, and if they are instantiated
|
||||
// then we won't be able to do any factory post processin' on 'em...
|
||||
ArrayList factoryProcessorNames = new ArrayList();
|
||||
string[] names = GetObjectNamesForType(typeof (IObjectFactoryPostProcessor), true, false);
|
||||
foreach (string s in names)
|
||||
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
|
||||
ArrayList processedObjects = new ArrayList();
|
||||
|
||||
if (objectFactory is IObjectDefinitionRegistry)
|
||||
{
|
||||
factoryProcessorNames.Add(s);
|
||||
IObjectDefinitionRegistry registry = (IObjectDefinitionRegistry)objectFactory;
|
||||
ArrayList regularPostProcessors = new ArrayList();
|
||||
ArrayList registryPostProcessors = new ArrayList();
|
||||
|
||||
foreach (IObjectFactoryPostProcessor factoryProcessor in ObjectFactoryPostProcessors)
|
||||
{
|
||||
if (factoryProcessor is IObjectDefinitionRegistryPostProcessor)
|
||||
{
|
||||
((IObjectDefinitionRegistryPostProcessor)factoryProcessor).PostProcessObjectDefinitionRegistry(registry);
|
||||
registryPostProcessors.Add(factoryProcessor);
|
||||
}
|
||||
else
|
||||
{
|
||||
regularPostProcessors.Add(factoryProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
IDictionary objectMap = objectFactory.GetObjectsOfType(typeof(IObjectDefinitionRegistryPostProcessor), true, false);
|
||||
|
||||
ArrayList registryPostProcessorObjects = new ArrayList(objectMap.Values);
|
||||
registryPostProcessorObjects.Sort(new OrderComparator());
|
||||
|
||||
foreach (System.Object processor in registryPostProcessorObjects)
|
||||
{
|
||||
((IObjectDefinitionRegistryPostProcessor)processor).PostProcessObjectDefinitionRegistry(registry);
|
||||
}
|
||||
|
||||
InvokeObjectFactoryPostProcessors(registryPostProcessors, objectFactory);
|
||||
InvokeObjectFactoryPostProcessors(registryPostProcessorObjects, objectFactory);
|
||||
InvokeObjectFactoryPostProcessors(regularPostProcessors, objectFactory);
|
||||
|
||||
// processedObjects.Add(objectMap.Keys);
|
||||
|
||||
foreach (DictionaryEntry entry in objectMap)
|
||||
{
|
||||
processedObjects.Add(entry.Key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
foreach (IObjectFactoryPostProcessor factoryProcessor in ObjectFactoryPostProcessors)
|
||||
{
|
||||
// Invoke factory processors registered with the context instance.
|
||||
factoryProcessor.PostProcessObjectFactory(objectFactory);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not initialize FactoryBeans here: We need to leave all regular beans
|
||||
// uninitialized to let the bean factory post-processors apply to them!
|
||||
ArrayList factoryProcessorNames = new ArrayList();
|
||||
string[] names = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false);
|
||||
foreach (string name in names)
|
||||
{
|
||||
factoryProcessorNames.Add(name);
|
||||
}
|
||||
|
||||
// Separate between ObjectFactoryPostProcessors that implement PriorityOrdered,
|
||||
// Ordered, and the rest.
|
||||
ArrayList priorityOrderedFactoryProcessors = new ArrayList();
|
||||
ArrayList orderedFactoryProcessorsNames = new ArrayList();
|
||||
ArrayList nonOrderedFactoryProcessorNames = new ArrayList();
|
||||
|
||||
|
||||
for (int i = 0; i < factoryProcessorNames.Count; ++i)
|
||||
{
|
||||
string processorName = (string) factoryProcessorNames[i];
|
||||
if (IsTypeMatch(processorName, typeof(IPriorityOrdered)))
|
||||
string processorName = (string)factoryProcessorNames[i];
|
||||
if (processedObjects.Contains(processorName))
|
||||
{
|
||||
//skip -- already processed in first phase above
|
||||
Debug.WriteLine("");
|
||||
}
|
||||
else if (IsTypeMatch(processorName, typeof(IPriorityOrdered)))
|
||||
{
|
||||
priorityOrderedFactoryProcessors.Add(ObjectFactory.GetObject(processorName, typeof(IObjectFactoryPostProcessor)));
|
||||
}
|
||||
else if (IsTypeMatch(processorName, typeof(IOrdered)))
|
||||
{
|
||||
orderedFactoryProcessorsNames.Add(processorName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nonOrderedFactoryProcessorNames.Add(processorName);
|
||||
@@ -527,17 +586,17 @@ namespace Spring.Context.Support
|
||||
foreach (string orderedFactoryProcessorsName in orderedFactoryProcessorsNames)
|
||||
{
|
||||
orderedFactoryProcessors.Add(ObjectFactory.GetObject(orderedFactoryProcessorsName,
|
||||
typeof (IObjectFactoryPostProcessor)));
|
||||
typeof(IObjectFactoryPostProcessor)));
|
||||
}
|
||||
orderedFactoryProcessors.Sort(new OrderComparator());
|
||||
InvokeObjectFactoryPostProcessors(orderedFactoryProcessors, ObjectFactory);
|
||||
|
||||
|
||||
// and then the unordered ones...
|
||||
ArrayList nonOrderedPostProcessors = new ArrayList();
|
||||
foreach (string nonOrderedFactoryProcessorName in nonOrderedFactoryProcessorNames)
|
||||
{
|
||||
nonOrderedPostProcessors.Add(ObjectFactory.GetObject(nonOrderedFactoryProcessorName,
|
||||
typeof (IObjectFactoryPostProcessor)));
|
||||
typeof(IObjectFactoryPostProcessor)));
|
||||
}
|
||||
InvokeObjectFactoryPostProcessors(nonOrderedPostProcessors, ObjectFactory);
|
||||
|
||||
@@ -563,7 +622,7 @@ namespace Spring.Context.Support
|
||||
// Now will find any additional IObjectFactoryPostProcessors that implement IPriorityOrdered that may have been
|
||||
// resolved due to using TypeAlias
|
||||
string[] factoryProcessorNamesAfterTypeAlias = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false);
|
||||
priorityOrderedFactoryProcessors.Clear();
|
||||
priorityOrderedFactoryProcessors.Clear();
|
||||
foreach (string factoryProcessorName in factoryProcessorNamesAfterTypeAlias)
|
||||
{
|
||||
if (!factoryProcessorNames.Contains(factoryProcessorName))
|
||||
@@ -912,10 +971,7 @@ namespace Spring.Context.Support
|
||||
|
||||
#endregion
|
||||
|
||||
foreach (IObjectFactoryPostProcessor factoryProcessor in ObjectFactoryPostProcessors)
|
||||
{
|
||||
factoryProcessor.PostProcessObjectFactory(objectFactory);
|
||||
}
|
||||
|
||||
|
||||
#region Instrumentation
|
||||
|
||||
@@ -939,7 +995,7 @@ namespace Spring.Context.Support
|
||||
|
||||
#endregion
|
||||
|
||||
InvokeObjectFactoryPostProcessors();
|
||||
InvokeObjectFactoryPostProcessors(objectFactory);
|
||||
|
||||
RegisterObjectPostProcessors(objectFactory);
|
||||
InitEventRegistry();
|
||||
|
||||
153
src/Spring/Spring.Core/ContextClassDiagram.cd
Normal file
153
src/Spring/Spring.Core/ContextClassDiagram.cd
Normal file
@@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="Spring.Context.Support.AbstractApplicationContext" Collapsed="true">
|
||||
<Position X="2.75" Y="8.75" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>SHQRYAEIiGBAtMBASYTEWAQkWBAiChEMaAACCAFBXMg=</HashCode>
|
||||
<FileName>Context\Support\AbstractApplicationContext.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="Spring.Context.Support.AbstractXmlApplicationContext" Collapsed="true">
|
||||
<Position X="1" Y="10.25" Width="2.25" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQACAAAAABAAACBAAQAAQAAABAAAAAAABAAAAACAEA=</HashCode>
|
||||
<FileName>Context\Support\AbstractXmlApplicationContext.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Spring.Context.Support.GenericApplicationContext" Collapsed="true">
|
||||
<Position X="4" Y="10.25" Width="2.25" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQAAAAAAAAAAAAAAAQAAAAAABAAIAAAAAAAAAAEAAA=</HashCode>
|
||||
<FileName>Context\Support\GenericApplicationContext.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Spring.Context.Support.XmlApplicationContext" Collapsed="true">
|
||||
<Position X="1.25" Y="11.75" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAACAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAIAEAAA=</HashCode>
|
||||
<FileName>Context\Support\XmlApplicationContext.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Spring.Context.Support.StaticApplicationContext" Collapsed="true">
|
||||
<Position X="4.25" Y="11.75" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAEAAAAAAAAAAAAIAAQAAAAAAgAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Context\Support\StaticApplicationContext.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Spring.Core.IO.ConfigurableResourceLoader" Collapsed="true">
|
||||
<Position X="2.5" Y="7.5" Width="2.25" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAggAAAQAAAAAABAAAAAAAAAAASAAAAAA=</HashCode>
|
||||
<FileName>Core\IO\ConfigurableResourceLoader.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Interface Name="Spring.Context.IConfigurableApplicationContext" Collapsed="true">
|
||||
<Position X="9.5" Y="5.5" Width="2.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEA=</HashCode>
|
||||
<FileName>Context\IConfigurableApplicationContext.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Context.IApplicationContext" Collapsed="true">
|
||||
<Position X="10" Y="3.5" Width="1.75" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAEAAAAACAAAQAAAAAAAAAAAAAAAAACAA=</HashCode>
|
||||
<FileName>Context\IApplicationContext.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Context.ILifecycle" Collapsed="true">
|
||||
<Position X="13" Y="4.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAACAAAAAAAAAAQAAAAAAAAAAAIAAAAAAAAAA=</HashCode>
|
||||
<FileName>Context\ILifecycle.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Factory.IObjectFactory" Collapsed="true">
|
||||
<Position X="6.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ABAAAAAAAAAAIIAACIAACAAAAAAAAgEMAAAAAAAAAIA=</HashCode>
|
||||
<FileName>Objects\Factory\IObjectFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Factory.Config.IAutowireCapableObjectFactory" Collapsed="true">
|
||||
<Position X="3.25" Y="2" Width="2.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAACAAAAAAAAIAAQAAAAgEAAAAAAAAAA=</HashCode>
|
||||
<FileName>Objects\Factory\Config\IAutowireCapableObjectFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Factory.IHierarchicalObjectFactory" Collapsed="true">
|
||||
<Position X="6.5" Y="2" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAA=</HashCode>
|
||||
<FileName>Objects\Factory\IHierarchicalObjectFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Factory.IListableObjectFactory" Collapsed="true">
|
||||
<Position X="9.25" Y="2" Width="1.75" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CAAAAAAAAAAAAAAAQABAEAAAAAAAAAAACAAAAAAAAAA=</HashCode>
|
||||
<FileName>Objects\Factory\IListableObjectFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Factory.Config.IConfigurableListableObjectFactory" Collapsed="true">
|
||||
<Position X="5.75" Y="3.5" Width="2.75" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAIAAAIAEAAAgAAAAAAAAAAAACABAAAA=</HashCode>
|
||||
<FileName>Objects\Factory\Config\IConfigurableListableObjectFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Factory.Config.IConfigurableObjectFactory" Collapsed="true">
|
||||
<Position X="6.5" Y="5.5" Width="2.25" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAABCAAAAAAAAACAAAAQAAEAAAAAAAAAQAAEAA=</HashCode>
|
||||
<FileName>Objects\Factory\Config\IConfigurableObjectFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Factory.Config.ISingletonObjectRegistry" Collapsed="true">
|
||||
<Position X="2.5" Y="4" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAEAAAABAIAAAAAAAAAAAAAAAAAAAAAgAAAIA=</HashCode>
|
||||
<FileName>Objects\Factory\Config\ISingletonObjectRegistry.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Context.IMessageSource" Collapsed="true">
|
||||
<Position X="12.25" Y="2" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ACAAAAAAAAAAAAAAAAAAAAAACAAAABAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Context\IMessageSource.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Context.IApplicationEventPublisher" Collapsed="true">
|
||||
<Position X="14.5" Y="2" Width="2.25" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA=</HashCode>
|
||||
<FileName>Context\IApplicationEventPublisher.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Core.IO.IResourceLoader" Collapsed="true">
|
||||
<Position X="17.5" Y="2" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAA=</HashCode>
|
||||
<FileName>Core\IO\IResourceLoader.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Events.IEventRegistry" Collapsed="true">
|
||||
<Position X="19.75" Y="2" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAQAAAAAAAAIA=</HashCode>
|
||||
<FileName>Objects\Events\IEventRegistry.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="Spring.Objects.Factory.Support.IObjectDefinitionRegistry">
|
||||
<Position X="0.5" Y="0.75" Width="2.25" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CBAAAAAAAAAAAAAAQAAEEAAgABAAAAAAAAAAAAAAEAA=</HashCode>
|
||||
<FileName>Objects\Factory\Support\IObjectDefinitionRegistry.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Common.Logging;
|
||||
|
||||
namespace Spring.Objects.Factory.Parsing
|
||||
{
|
||||
public class FailFastProblemReporter : IProblemReporter
|
||||
{
|
||||
private ILog _logger = LogManager.GetLogger(typeof(FailFastProblemReporter));
|
||||
|
||||
public ILog Logger
|
||||
{
|
||||
get { return _logger; }
|
||||
}
|
||||
|
||||
public void Error(Problem problem)
|
||||
{
|
||||
_logger.Error(problem.Message);
|
||||
throw new ObjectDefinitionParsingException(problem);
|
||||
}
|
||||
|
||||
public void Fatal(Problem problem)
|
||||
{
|
||||
_logger.Fatal(problem.Message);
|
||||
throw new ObjectDefinitionParsingException(problem);
|
||||
}
|
||||
|
||||
public void Warning(Problem problem)
|
||||
{
|
||||
_logger.Warn(problem.Message);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
53
src/Spring/Spring.Core/Objects/Factory/Parsing/Location.cs
Normal file
53
src/Spring/Spring.Core/Objects/Factory/Parsing/Location.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Spring.Core.IO;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Objects.Factory.Parsing
|
||||
{
|
||||
public class Location
|
||||
{
|
||||
private IResource resource;
|
||||
private object source;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Location class.
|
||||
/// </summary>
|
||||
/// <param name="resource"></param>
|
||||
/// <param name="source"></param>
|
||||
public Location(IResource resource, object source)
|
||||
{
|
||||
//TODO: look into re-enabling this since resource *is* NULL when parsing config classes vs. acquiring IResources
|
||||
//AssertUtils.ArgumentNotNull(resource, "resource");
|
||||
this.resource = resource;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Location class.
|
||||
/// </summary>
|
||||
/// <param name="resource"></param>
|
||||
public Location(IResource resource)
|
||||
: this(resource, null)
|
||||
{
|
||||
|
||||
}
|
||||
public IResource Resource
|
||||
{
|
||||
get
|
||||
{
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
public object Source
|
||||
{
|
||||
get
|
||||
{
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Spring.Objects.Factory.Parsing
|
||||
{
|
||||
[Serializable]
|
||||
public class ObjectDefinitionParsingException : ObjectDefinitionStoreException
|
||||
{
|
||||
protected ObjectDefinitionParsingException(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ObjectDefinitionParsingException class.
|
||||
/// </summary>
|
||||
public ObjectDefinitionParsingException(Problem problem)
|
||||
: base(problem.Location.Resource, problem.ResourceDescription, problem.Message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
78
src/Spring/Spring.Core/Objects/Factory/Parsing/Problem.cs
Normal file
78
src/Spring/Spring.Core/Objects/Factory/Parsing/Problem.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Spring.Core.IO;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Objects.Factory.Parsing
|
||||
{
|
||||
public class Problem
|
||||
{
|
||||
private string _message;
|
||||
|
||||
private Location _location;
|
||||
|
||||
private Exception _rootCause;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Problem class.
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="resource"></param>
|
||||
public Problem(string message, Location location)
|
||||
: this(message, location, null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Problem class.
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="location"></param>
|
||||
/// <param name="rootCause"></param>
|
||||
public Problem(string message, Location location, Exception rootCause)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(message, "message");
|
||||
AssertUtils.ArgumentNotNull(location, "resource");
|
||||
|
||||
_message = message;
|
||||
_location = location;
|
||||
_rootCause = rootCause;
|
||||
}
|
||||
|
||||
public string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
return _message;
|
||||
}
|
||||
}
|
||||
|
||||
public Location Location
|
||||
{
|
||||
get
|
||||
{
|
||||
return _location;
|
||||
}
|
||||
}
|
||||
|
||||
public string ResourceDescription
|
||||
{
|
||||
get { return _location.Resource!=null ? _location.Resource.Description : string.Empty; }
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("Configuration problem: ");
|
||||
sb.Append(Message);
|
||||
sb.Append("\nOffending resource: ").Append(ResourceDescription);
|
||||
|
||||
return sb.ToString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Spring.Objects.Factory.Config;
|
||||
|
||||
namespace Spring.Objects.Factory.Support
|
||||
{
|
||||
public interface IObjectDefinitionRegistryPostProcessor : IObjectFactoryPostProcessor
|
||||
{
|
||||
void PostProcessObjectDefinitionRegistry(IObjectDefinitionRegistry registry);
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,7 @@ namespace Spring.Objects.Factory.Support
|
||||
{
|
||||
if (objectDefinition is ChildObjectDefinition)
|
||||
{
|
||||
generatedObjectName = ((ChildObjectDefinition) objectDefinition).ParentName + "$child";
|
||||
generatedObjectName = ((ChildObjectDefinition)objectDefinition).ParentName + "$child";
|
||||
}
|
||||
else if (objectDefinition.FactoryObjectName != null)
|
||||
{
|
||||
@@ -157,7 +157,7 @@ namespace Spring.Objects.Factory.Support
|
||||
throw new ObjectDefinitionStoreException(
|
||||
objectDefinition.ResourceDescription, String.Empty,
|
||||
"Unnamed object definition specifies neither 'Type' nor 'Parent' " +
|
||||
"nor 'FactoryObject' property values so a unique name cannot be generated.");
|
||||
"nor 'FactoryObject' property values so a unique name cannot be generated.");
|
||||
}
|
||||
generatedObjectName = "$nested";
|
||||
}
|
||||
@@ -166,14 +166,15 @@ namespace Spring.Objects.Factory.Support
|
||||
if (isInnerObject)
|
||||
{
|
||||
id = generatedObjectName + GENERATED_OBJECT_NAME_SEPARATOR + ObjectUtils.GetIdentityHexString(objectDefinition);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
int counter = -1;
|
||||
while (counter == -1 || registry.ContainsObjectDefinition(id))
|
||||
{
|
||||
counter++;
|
||||
id = generatedObjectName + GENERATED_OBJECT_NAME_SEPARATOR + counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
@@ -257,6 +258,15 @@ namespace Spring.Objects.Factory.Support
|
||||
return myHandler;
|
||||
}
|
||||
|
||||
|
||||
public static String RegisterWithGeneratedName(AbstractObjectDefinition definition, IObjectDefinitionRegistry registry)
|
||||
{
|
||||
String generatedName = GenerateObjectName(definition, registry, false);
|
||||
registry.RegisterObjectDefinition(generatedName, definition);
|
||||
return generatedName;
|
||||
}
|
||||
|
||||
|
||||
#region Constructor (s) / Destructor
|
||||
|
||||
// CLOVER:OFF
|
||||
|
||||
@@ -125,7 +125,15 @@
|
||||
<Compile Include="Collections\DictionarySet.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Collections\Generic\DictionarySet.cs" />
|
||||
<Compile Include="Collections\Generic\HashedSet.cs" />
|
||||
<Compile Include="Collections\Generic\ImmutableSet.cs" />
|
||||
<Compile Include="Collections\Generic\ISet.cs" />
|
||||
<Compile Include="Collections\Generic\OrderedSet.cs" />
|
||||
<Compile Include="Collections\Generic\ReadOnlyDictionary.cs" />
|
||||
<Compile Include="Collections\Generic\Set.cs" />
|
||||
<Compile Include="Collections\Generic\SortedSet.cs" />
|
||||
<Compile Include="Collections\Generic\SynchronizedSet.cs" />
|
||||
<Compile Include="Collections\HashedSet.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -695,7 +703,14 @@
|
||||
<Compile Include="Objects\Factory\Config\IVariableSource.cs" />
|
||||
<Compile Include="Objects\Factory\Config\VariableAccessor.cs" />
|
||||
<Compile Include="Objects\Factory\Config\VariablePlaceholderConfigurer.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\FailFastProblemReporter.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\IProblemReporter.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\Location.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\ObjectDefinitionParsingException.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\Problem.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\ReaderContext.cs" />
|
||||
<Compile Include="Objects\Factory\Support\IObjectDefinitionRegistryPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Support\ObjectScope.cs" />
|
||||
<Compile Include="Util\ConstructorInstantiationInfo.cs" />
|
||||
<Compile Include="Objects\Factory\Support\GenericObjectDefinition.cs" />
|
||||
<Compile Include="Objects\Factory\Support\IAutowireCandidateResolver.cs" />
|
||||
@@ -1203,6 +1218,7 @@
|
||||
<Compile Include="Validation\Validators\UrlValidator.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<None Include="ContextClassDiagram.cd" />
|
||||
<None Include="Expressions\Expression.g" />
|
||||
<EmbeddedResource Include="Objects\Factory\Xml\spring-tool-1.1.xsd">
|
||||
<SubType>
|
||||
@@ -1246,6 +1262,7 @@
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>rem $(ProjectDir)..\..\..\build-support\tools\antlr-2.7.6\antlr-2.7.6.exe -o $(ProjectDir)Expressions\Parser $(ProjectDir)Expressions\Expression.g
|
||||
|
||||
@@ -1417,6 +1417,65 @@ namespace Spring.Util
|
||||
MemberwiseCopyInternal(fromObject, toObject, smallerType);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method that uses reflection to return the value of a non-public field of a given object.
|
||||
/// </summary>
|
||||
/// <remarks>Useful in certain instances during testing to avoid the need to add protected properties, etc. to a class just to facilitate testing.</remarks>
|
||||
/// <param name="obj">The instance of the object from which to retrieve the field value.</param>
|
||||
/// <param name="fieldName">Name of the field on the object from which to retrieve the value.</param>
|
||||
/// <returns></returns>
|
||||
public static object GetInstanceFieldValue(object obj, string fieldName)
|
||||
{
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException("obj", "obj is null.");
|
||||
if (String.IsNullOrEmpty(fieldName))
|
||||
throw new ArgumentException("fieldName is null or empty.", "fieldName");
|
||||
|
||||
FieldInfo f = obj.GetType().GetField(fieldName, BindingFlags.SetField | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
if (f != null)
|
||||
return f.GetValue(obj);
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(string.Format("Non-public instance field '{0}' could not be found in class of type '{1}'", fieldName, obj.GetType().ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method that uses reflection to set the value of a non-public field of a given object.
|
||||
/// </summary>
|
||||
/// <remarks>Useful in certain instances during testing to avoid the need to add protected properties, etc. to a class just to facilitate testing.</remarks>
|
||||
/// <param name="obj">The instance of the object from which to set the field value.</param>
|
||||
/// <param name="fieldName">Name of the field on the object to which to set the value.</param>
|
||||
/// <param name="fieldValue">The field value to set.</param>
|
||||
public static void SetInstanceFieldValue(object obj, string fieldName, object fieldValue)
|
||||
{
|
||||
|
||||
if (obj == null)
|
||||
throw new ArgumentNullException("obj", "obj is null.");
|
||||
if (String.IsNullOrEmpty(fieldName))
|
||||
throw new ArgumentException("fieldName is null or empty.", "fieldName");
|
||||
if (fieldValue == null)
|
||||
throw new ArgumentNullException("fieldValue", "fieldValue is null.");
|
||||
|
||||
FieldInfo f = obj.GetType().GetField(fieldName, BindingFlags.SetField | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (f != null)
|
||||
{
|
||||
if (f.FieldType != fieldValue.GetType())
|
||||
throw new ArgumentException(string.Format("fieldValue for fieldName '{0}' of object type '{1}' must be of type '{2}' but was of type '{3}'", fieldName, obj.GetType().ToString(), f.FieldType.ToString(), fieldValue.GetType().ToString()), "fieldValue");
|
||||
|
||||
f.SetValue(obj, fieldValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(string.Format("Non-public instance field '{0}' could not be found in class of type '{1}'", fieldName, obj.GetType().ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if NET_2_0
|
||||
private static void MemberwiseCopyInternal(object fromObject, object toObject, Type smallerType)
|
||||
{
|
||||
|
||||
@@ -169,7 +169,6 @@
|
||||
</Compile>
|
||||
<Compile Include="Objects\Factory\Support\ChildWebObjectDefinition.cs" />
|
||||
<Compile Include="Objects\Factory\Support\IWebObjectDefinition.cs" />
|
||||
<Compile Include="Objects\Factory\Support\ObjectScope.cs" />
|
||||
<Compile Include="Objects\Factory\Support\RootWebObjectDefinition.cs" />
|
||||
<Compile Include="Objects\Factory\Support\WebInstantiationStrategy.cs" />
|
||||
<Compile Include="Objects\Factory\Support\WebObjectDefinitionFactory.cs" />
|
||||
|
||||
Reference in New Issue
Block a user