performance improvements

fixed SynchronizedHashtable
SPRNET-974: support private ctors with ConstructorNode
SPRNET-975: treat alias case insensitive as well
SPRNET-976: defered registering WebObjectFactory event handlers with VirtualEnvironment to when they are really needed
SPRNET-977: avoid unnecessary usages of HttpContextSwitch in WebObjectFactory.ConfigureObject()
added tests
added VirtualEnvironment HttpSessionState/HttpRequest abstraction
This commit is contained in:
eeichinger
2008-07-20 12:10:15 +00:00
parent d4e4d324ab
commit 733402b15f
35 changed files with 4386 additions and 3415 deletions

View File

@@ -211,12 +211,12 @@ Global
{E2689B4A-A951-420E-A274-BE5EBCD5F8D8}.Release-1.1.Build.0 = Release-1.1|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug.ActiveCfg = Debug|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug.Build.0 = Debug|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug-1.1.ActiveCfg = Debug|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug-1.1.Build.0 = Debug|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug-1.1.ActiveCfg = Debug-1.1|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Debug-1.1.Build.0 = Debug-1.1|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release.ActiveCfg = Release|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release.Build.0 = Release|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release-1.1.ActiveCfg = Release|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release-1.1.Build.0 = Release|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release-1.1.ActiveCfg = Release-1.1|.NET
{2E12AE3E-5690-46A5-9F89-80F1D3004ADB}.Release-1.1.Build.0 = Release-1.1|.NET
{C17B27C2-4343-45BA-9A21-73C3CEC19BAD}.Debug.ActiveCfg = Debug|.NET
{C17B27C2-4343-45BA-9A21-73C3CEC19BAD}.Debug.Build.0 = Debug|.NET
{C17B27C2-4343-45BA-9A21-73C3CEC19BAD}.Debug-1.1.ActiveCfg = Debug|.NET

View File

@@ -318,7 +318,6 @@ Global
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Release|.NET.ActiveCfg = Release|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Release|.NET.Build.0 = Release|Any CPU
{130E1609-45A7-4F65-B112-105F2DD3E2CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -330,7 +329,6 @@ Global
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|.NET.ActiveCfg = Release|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|.NET.Build.0 = Release|Any CPU
{4A07E150-ED90-407C-8CAD-4760444DDFD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -354,7 +352,6 @@ Global
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Release|.NET.ActiveCfg = Release|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Release|.NET.Build.0 = Release|Any CPU
{94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -397,7 +394,6 @@ Global
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Release|.NET.ActiveCfg = Release|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AEB1578C-9018-4D49-B440-789F38DD2F29}.Release|Any CPU.Build.0 = Release|Any CPU
@@ -407,7 +403,6 @@ Global
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Release|.NET.ActiveCfg = Release|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA7A6931-7DBE-4A32-A312-51FAD2E80332}.Release|Any CPU.Build.0 = Release|Any CPU

View File

@@ -0,0 +1,87 @@
using System.Collections;
using System.Globalization;
using Spring.Util;
namespace Spring.Collections
{
/// <summary>
/// Provides a performance improved hashtable with case-insensitive (string-only! based) key handling.
/// </summary>
/// <author>Erich Eichinger</author>
public class CaseInsensitiveHashtable : Hashtable
{
private readonly TextInfo _textInfo;
private readonly CompareInfo _compareInfo;
/// <summary>
/// Creates a case-insensitive hashtable using <see cref="CultureInfo.CurrentCulture"/>.
/// </summary>
public CaseInsensitiveHashtable()
: this(null, CultureInfo.CurrentCulture)
{}
/// <summary>
/// Creates a case-insensitive hashtable using the given <see cref="CultureInfo"/>.
/// </summary>
/// <param name="culture">the <see cref="CultureInfo"/> to calculate the hashcode</param>
public CaseInsensitiveHashtable(CultureInfo culture)
: this(null, culture)
{}
/// <summary>
/// Creates a case-insensitive hashtable using the given <see cref="CultureInfo"/>, initially
/// populated with entries from another dictionary.
/// </summary>
/// <param name="d">the dictionary to copy entries from</param>
/// <param name="culture">the <see cref="CultureInfo"/> to calculate the hashcode</param>
public CaseInsensitiveHashtable(IDictionary d, CultureInfo culture)
:this(d, culture.TextInfo, culture.CompareInfo)
{}
/// <summary>
/// Creates a case-insensitive hashtable using the given <see cref="CultureInfo"/>, initially
/// populated with entries from another dictionary.
/// </summary>
protected CaseInsensitiveHashtable(IDictionary d, TextInfo textInfo, CompareInfo compareInfo)
{
AssertUtils.ArgumentNotNull(textInfo, "textInfo");
_textInfo = textInfo;
_compareInfo = compareInfo;
if (d != null)
{
IDictionaryEnumerator enumerator = d.GetEnumerator();
while (enumerator.MoveNext())
{
this.Add(enumerator.Key, enumerator.Value);
}
}
}
/// <summary>
/// Calculate the hashcode of the given string key, using the configured culture.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
protected override int GetHash(object key)
{
return _textInfo.ToLower((string) key).GetHashCode();
}
/// <summary>
/// Compares two keys
/// </summary>
protected override bool KeyEquals(object item, object key)
{
return 0==_compareInfo.Compare((string) item, (string) key, CompareOptions.IgnoreCase);
}
/// <summary>
/// Creates a shallow copy of the current instance.
/// </summary>
public override object Clone()
{
return new CaseInsensitiveHashtable(this, _textInfo, _compareInfo );
}
}
}

View File

@@ -1,366 +1,397 @@
#region License
/*
* Copyright 2002-2004 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System;
using System.Collections;
using Spring.Util;
namespace Spring.Collections
{
/// <summary>
/// Synchronized <see cref="Hashtable"/> that, unlike hashtable created
/// using <see cref="Hashtable.Synchronized"/> method, synchronizes
/// reads from the underlying hashtable in addition to writes.
/// </summary>
/// <remarks>
/// <p>
/// In addition to synchronizing reads, this implementation also fixes
/// IEnumerator/ICollection issue described at
/// http://msdn.microsoft.com/en-us/netframework/aa570326.aspx
/// (search for SynchronizedHashtable for issue description), by implementing
/// <see cref="IEnumerator"/> interface explicitly, and returns thread safe enumerator
/// implementations as well.
/// </p>
/// <p>
/// This class should be used whenever a truly synchronized <see cref="Hashtable"/>
/// is needed.
/// </p>
/// </remarks>
/// <author>Aleksandar Seovic</author>
[Serializable]
public class SynchronizedHashtable : IDictionary, ICollection, IEnumerable, ICloneable
{
private readonly Hashtable _table;
#region Constructors
/// <summary>
/// Initializes a new instance of <see cref="SynchronizedHashtable"/>
/// </summary>
public SynchronizedHashtable()
{
this._table = new Hashtable();
}
/// <summary>
/// Initializes a new instance of <see cref="SynchronizedHashtable"/>, copying inital entries from <param name="dictionary"/>.
/// </summary>
public SynchronizedHashtable(IDictionary dictionary)
{
AssertUtils.ArgumentNotNull(dictionary, "dictionary");
this._table = new Hashtable(dictionary);
}
#endregion
#region Properties
///<summary>
///Gets a value indicating whether the <see cref="T:System.Collections.IDictionary"></see> object is read-only.
///</summary>
///<returns>
///true if the <see cref="T:System.Collections.IDictionary"></see> object is read-only; otherwise, false.
///</returns>
public bool IsReadOnly
{
get
{
lock (SyncRoot)
{
return _table.IsReadOnly;
}
}
}
///<summary>
///Gets a value indicating whether the <see cref="T:System.Collections.IDictionary"></see> object has a fixed size.
///</summary>
///<returns>
///true if the <see cref="T:System.Collections.IDictionary"></see> object has a fixed size; otherwise, false.
///</returns>
public bool IsFixedSize
{
get
{
lock (SyncRoot)
{
return _table.IsFixedSize;
}
}
}
///<summary>
///Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"></see> is synchronized (thread safe).
///</summary>
///<returns>
///true if access to the <see cref="T:System.Collections.ICollection"></see> is synchronized (thread safe); otherwise, false.
///</returns>
public bool IsSynchronized
{
get { return true; }
}
///<summary>
///Gets an <see cref="T:System.Collections.ICollection"></see> object containing the keys of the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<returns>
///An <see cref="T:System.Collections.ICollection"></see> object containing the keys of the <see cref="T:System.Collections.IDictionary"></see> object.
///</returns>
public ICollection Keys
{
get
{
lock (SyncRoot)
{
return _table.Keys;
}
}
}
///<summary>
///Gets an <see cref="T:System.Collections.ICollection"></see> object containing the values in the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<returns>
///An <see cref="T:System.Collections.ICollection"></see> object containing the values in the <see cref="T:System.Collections.IDictionary"></see> object.
///</returns>
public ICollection Values
{
get
{
lock (SyncRoot)
{
return _table.Values;
}
}
}
///<summary>
///Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"></see>.
///</summary>
///<returns>
///An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"></see>.
///</returns>
public object SyncRoot
{
get { return _table.SyncRoot; }
}
///<summary>
///Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"></see>.
///</summary>
///<returns>
///The number of elements contained in the <see cref="T:System.Collections.ICollection"></see>.
///</returns>
public int Count
{
get
{
lock (SyncRoot)
{
return _table.Count;
}
}
}
#endregion
#region Methods
///<summary>
///Adds an element with the provided key and value to the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<param name="value">The <see cref="T:System.Object"></see> to use as the value of the element to add. </param>
///<param name="key">The <see cref="T:System.Object"></see> to use as the key of the element to add. </param>
///<exception cref="T:System.ArgumentException">An element with the same key already exists in the <see cref="T:System.Collections.IDictionary"></see> object. </exception>
///<exception cref="T:System.ArgumentNullException">key is null. </exception>
///<exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IDictionary"></see> is read-only.-or- The <see cref="T:System.Collections.IDictionary"></see> has a fixed size. </exception><filterpriority>2</filterpriority>
public void Add(object key, object value)
{
lock (SyncRoot)
{
_table.Add(key, value);
}
}
///<summary>
///Removes all elements from the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IDictionary"></see> object is read-only. </exception><filterpriority>2</filterpriority>
public void Clear()
{
lock (SyncRoot)
{
_table.Clear();
}
}
///<summary>
///Creates a new object that is a copy of the current instance.
///</summary>
///<returns>
///A new object that is a copy of this instance.
///</returns>
public object Clone()
{
lock (SyncRoot)
{
return new SynchronizedHashtable(this);
}
}
///<summary>
///Determines whether the <see cref="T:System.Collections.IDictionary"></see> object contains an element with the specified key.
///</summary>
///<returns>
///true if the <see cref="T:System.Collections.IDictionary"></see> contains an element with the key; otherwise, false.
///</returns>
///<param name="key">The key to locate in the <see cref="T:System.Collections.IDictionary"></see> object.</param>
///<exception cref="T:System.ArgumentNullException">key is null. </exception><filterpriority>2</filterpriority>
public bool Contains(object key)
{
lock (SyncRoot)
{
return _table.Contains(key);
}
}
///<summary>
/// Returns, whether this <see cref="IDictionary"/> contains an entry with the specified <paramref name="key"/>.
///</summary>
///<param name="key">The key to look for</param>
///<returns><see lang="true"/>, if this <see cref="IDictionary"/> contains an entry with this <paramref name="key"/></returns>
public bool ContainsKey(object key)
{
lock (SyncRoot)
{
return _table.ContainsKey(key);
}
}
///<summary>
/// Returns, whether this <see cref="IDictionary"/> contains an entry with the specified <paramref name="value"/>.
///</summary>
///<param name="value">The val<61>e to look for</param>
///<returns><see lang="true"/>, if this <see cref="IDictionary"/> contains an entry with this <paramref name="value"/></returns>
public bool ContainsValue(object value)
{
lock (SyncRoot)
{
return _table.ContainsValue(value);
}
}
///<summary>
///Copies the elements of the <see cref="T:System.Collections.ICollection"></see> to an <see cref="T:System.Array"></see>, starting at a particular <see cref="T:System.Array"></see> index.
///</summary>
///<param name="array">The one-dimensional <see cref="T:System.Array"></see> that is the destination of the elements copied from <see cref="T:System.Collections.ICollection"></see>. The <see cref="T:System.Array"></see> must have zero-based indexing. </param>
///<param name="index">The zero-based index in array at which copying begins. </param>
///<exception cref="T:System.ArgumentNullException">array is null. </exception>
///<exception cref="T:System.ArgumentException">The type of the source <see cref="T:System.Collections.ICollection"></see> cannot be cast automatically to the type of the destination array. </exception>
///<exception cref="T:System.ArgumentOutOfRangeException">index is less than zero. </exception>
///<exception cref="T:System.ArgumentException">array is multidimensional.-or- index is equal to or greater than the length of array.-or- The number of elements in the source <see cref="T:System.Collections.ICollection"></see> is greater than the available space from index to the end of the destination array. </exception><filterpriority>2</filterpriority>
public void CopyTo(Array array, int index)
{
lock (SyncRoot)
{
_table.CopyTo(array, index);
}
}
///<summary>
///Returns an <see cref="T:System.Collections.IDictionaryEnumerator"></see> object for the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<returns>
///An <see cref="T:System.Collections.IDictionaryEnumerator"></see> object for the <see cref="T:System.Collections.IDictionary"></see> object.
///</returns>
public IDictionaryEnumerator GetEnumerator()
{
lock (SyncRoot)
{
return new SynchronizedDictionaryEnumerator(SyncRoot, _table.GetEnumerator());
}
}
///<summary>
///Removes the element with the specified key from the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<param name="key">The key of the element to remove. </param>
///<exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IDictionary"></see> object is read-only.-or- The <see cref="T:System.Collections.IDictionary"></see> has a fixed size. </exception>
///<exception cref="T:System.ArgumentNullException">key is null. </exception><filterpriority>2</filterpriority>
public void Remove(object key)
{
lock (SyncRoot)
{
_table.Remove(key);
}
}
#endregion
#region IEnumerable implementation
///<summary>
///Returns an enumerator that iterates through a collection.
///</summary>
///<returns>
///An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection.
///</returns>
IEnumerator IEnumerable.GetEnumerator()
{
lock (SyncRoot)
{
return new SynchronizedEnumerator(SyncRoot, ((IEnumerable) _table).GetEnumerator());
}
}
#endregion
#region Indexer
///<summary>
///Gets or sets the element with the specified key.
///</summary>
///<returns>
///The element with the specified key.
///</returns>
///<param name="key">The key of the element to get or set. </param>
///<exception cref="T:System.NotSupportedException">The property is set and the <see cref="T:System.Collections.IDictionary"></see> object is read-only.-or- The property is set, key does not exist in the collection, and the <see cref="T:System.Collections.IDictionary"></see> has a fixed size. </exception>
///<exception cref="T:System.ArgumentNullException">key is null. </exception><filterpriority>2</filterpriority>
public object this[object key]
{
get
{
lock (SyncRoot)
{
return _table[key];
}
}
set
{
lock (SyncRoot)
{
_table[key] = value;
}
}
}
#endregion
}
#region License
/*
* Copyright 2002-2004 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System;
using System.Collections;
using System.Collections.Specialized;
using Spring.Util;
namespace Spring.Collections
{
/// <summary>
/// Synchronized <see cref="Hashtable"/> that, unlike hashtable created
/// using <see cref="Hashtable.Synchronized"/> method, synchronizes
/// reads from the underlying hashtable in addition to writes.
/// </summary>
/// <remarks>
/// <p>
/// In addition to synchronizing reads, this implementation also fixes
/// IEnumerator/ICollection issue described at
/// http://msdn.microsoft.com/en-us/netframework/aa570326.aspx
/// (search for SynchronizedHashtable for issue description), by implementing
/// <see cref="IEnumerator"/> interface explicitly, and returns thread safe enumerator
/// implementations as well.
/// </p>
/// <p>
/// This class should be used whenever a truly synchronized <see cref="Hashtable"/>
/// is needed.
/// </p>
/// </remarks>
/// <author>Aleksandar Seovic</author>
[Serializable]
public class SynchronizedHashtable : IDictionary, ICollection, IEnumerable, ICloneable
{
private readonly bool _ignoreCase;
private readonly Hashtable _table;
#region Constructors
/// <summary>
/// Initializes a new instance of <see cref="SynchronizedHashtable"/>
/// </summary>
public SynchronizedHashtable()
: this(new Hashtable(), false)
{ }
/// <summary>
/// Initializes a new instance of <see cref="SynchronizedHashtable"/>
/// </summary>
public SynchronizedHashtable(bool ignoreCase)
: this(new Hashtable(), ignoreCase)
{ }
/// <summary>
/// Initializes a new instance of <see cref="SynchronizedHashtable"/>, copying inital entries from <param name="dictionary"/>
/// handling keys depending on <param name="ignoreCase"/>.
/// </summary>
public SynchronizedHashtable(IDictionary dictionary, bool ignoreCase)
{
AssertUtils.ArgumentNotNull(dictionary, "dictionary");
this._table = (ignoreCase) ? CollectionsUtil.CreateCaseInsensitiveHashtable(dictionary) : new Hashtable(dictionary);
this._ignoreCase = ignoreCase;
}
/// <summary>
/// Creates a <see cref="SynchronizedHashtable"/> instance that
/// synchronizes access to the underlying <see cref="Hashtable"/>.
/// </summary>
/// <param name="other">the hashtable to be synchronized</param>
protected SynchronizedHashtable(Hashtable other)
{
AssertUtils.ArgumentNotNull(other, "other");
this._table = other;
}
/// <summary>
/// Creates a <see cref="SynchronizedHashtable"/> wrapper that synchronizes
/// access to the passed <see cref="Hashtable"/>.
/// </summary>
/// <param name="other">the hashtable to be synchronized</param>
public static SynchronizedHashtable Wrap(Hashtable other)
{
return new SynchronizedHashtable(other);
}
#endregion
#region Properties
///<summary>
///Gets a value indicating whether the <see cref="T:System.Collections.IDictionary"></see> object is read-only.
///</summary>
///<returns>
///true if the <see cref="T:System.Collections.IDictionary"></see> object is read-only; otherwise, false.
///</returns>
public bool IsReadOnly
{
get
{
lock (SyncRoot)
{
return _table.IsReadOnly;
}
}
}
///<summary>
///Gets a value indicating whether the <see cref="T:System.Collections.IDictionary"></see> object has a fixed size.
///</summary>
///<returns>
///true if the <see cref="T:System.Collections.IDictionary"></see> object has a fixed size; otherwise, false.
///</returns>
public bool IsFixedSize
{
get
{
lock (SyncRoot)
{
return _table.IsFixedSize;
}
}
}
///<summary>
///Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"></see> is synchronized (thread safe).
///</summary>
///<returns>
///true if access to the <see cref="T:System.Collections.ICollection"></see> is synchronized (thread safe); otherwise, false.
///</returns>
public bool IsSynchronized
{
get { return true; }
}
///<summary>
///Gets an <see cref="T:System.Collections.ICollection"></see> object containing the keys of the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<returns>
///An <see cref="T:System.Collections.ICollection"></see> object containing the keys of the <see cref="T:System.Collections.IDictionary"></see> object.
///</returns>
public ICollection Keys
{
get
{
lock (SyncRoot)
{
return _table.Keys;
}
}
}
///<summary>
///Gets an <see cref="T:System.Collections.ICollection"></see> object containing the values in the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<returns>
///An <see cref="T:System.Collections.ICollection"></see> object containing the values in the <see cref="T:System.Collections.IDictionary"></see> object.
///</returns>
public ICollection Values
{
get
{
lock (SyncRoot)
{
return _table.Values;
}
}
}
///<summary>
///Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"></see>.
///</summary>
///<returns>
///An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"></see>.
///</returns>
public object SyncRoot
{
get { return _table.SyncRoot; }
}
///<summary>
///Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"></see>.
///</summary>
///<returns>
///The number of elements contained in the <see cref="T:System.Collections.ICollection"></see>.
///</returns>
public int Count
{
get
{
lock (SyncRoot)
{
return _table.Count;
}
}
}
#endregion
#region Methods
///<summary>
///Adds an element with the provided key and value to the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<param name="value">The <see cref="T:System.Object"></see> to use as the value of the element to add. </param>
///<param name="key">The <see cref="T:System.Object"></see> to use as the key of the element to add. </param>
///<exception cref="T:System.ArgumentException">An element with the same key already exists in the <see cref="T:System.Collections.IDictionary"></see> object. </exception>
///<exception cref="T:System.ArgumentNullException">key is null. </exception>
///<exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IDictionary"></see> is read-only.-or- The <see cref="T:System.Collections.IDictionary"></see> has a fixed size. </exception><filterpriority>2</filterpriority>
public void Add(object key, object value)
{
lock (SyncRoot)
{
_table.Add(key, value);
}
}
///<summary>
///Removes all elements from the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IDictionary"></see> object is read-only. </exception><filterpriority>2</filterpriority>
public void Clear()
{
lock (SyncRoot)
{
_table.Clear();
}
}
///<summary>
///Creates a new object that is a copy of the current instance.
///</summary>
///<returns>
///A new object that is a copy of this instance.
///</returns>
public object Clone()
{
lock (SyncRoot)
{
return new SynchronizedHashtable(this, _ignoreCase);
}
}
///<summary>
///Determines whether the <see cref="T:System.Collections.IDictionary"></see> object contains an element with the specified key.
///</summary>
///<returns>
///true if the <see cref="T:System.Collections.IDictionary"></see> contains an element with the key; otherwise, false.
///</returns>
///<param name="key">The key to locate in the <see cref="T:System.Collections.IDictionary"></see> object.</param>
///<exception cref="T:System.ArgumentNullException">key is null. </exception><filterpriority>2</filterpriority>
public bool Contains(object key)
{
lock (SyncRoot)
{
return _table.Contains(key);
}
}
///<summary>
/// Returns, whether this <see cref="IDictionary"/> contains an entry with the specified <paramref name="key"/>.
///</summary>
///<param name="key">The key to look for</param>
///<returns><see lang="true"/>, if this <see cref="IDictionary"/> contains an entry with this <paramref name="key"/></returns>
public bool ContainsKey(object key)
{
lock (SyncRoot)
{
return _table.ContainsKey(key);
}
}
///<summary>
/// Returns, whether this <see cref="IDictionary"/> contains an entry with the specified <paramref name="value"/>.
///</summary>
///<param name="value">The val<61>e to look for</param>
///<returns><see lang="true"/>, if this <see cref="IDictionary"/> contains an entry with this <paramref name="value"/></returns>
public bool ContainsValue(object value)
{
lock (SyncRoot)
{
return _table.ContainsValue(value);
}
}
///<summary>
///Copies the elements of the <see cref="T:System.Collections.ICollection"></see> to an <see cref="T:System.Array"></see>, starting at a particular <see cref="T:System.Array"></see> index.
///</summary>
///<param name="array">The one-dimensional <see cref="T:System.Array"></see> that is the destination of the elements copied from <see cref="T:System.Collections.ICollection"></see>. The <see cref="T:System.Array"></see> must have zero-based indexing. </param>
///<param name="index">The zero-based index in array at which copying begins. </param>
///<exception cref="T:System.ArgumentNullException">array is null. </exception>
///<exception cref="T:System.ArgumentException">The type of the source <see cref="T:System.Collections.ICollection"></see> cannot be cast automatically to the type of the destination array. </exception>
///<exception cref="T:System.ArgumentOutOfRangeException">index is less than zero. </exception>
///<exception cref="T:System.ArgumentException">array is multidimensional.-or- index is equal to or greater than the length of array.-or- The number of elements in the source <see cref="T:System.Collections.ICollection"></see> is greater than the available space from index to the end of the destination array. </exception><filterpriority>2</filterpriority>
public void CopyTo(Array array, int index)
{
lock (SyncRoot)
{
_table.CopyTo(array, index);
}
}
///<summary>
///Returns an <see cref="T:System.Collections.IDictionaryEnumerator"></see> object for the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<returns>
///An <see cref="T:System.Collections.IDictionaryEnumerator"></see> object for the <see cref="T:System.Collections.IDictionary"></see> object.
///</returns>
public IDictionaryEnumerator GetEnumerator()
{
lock (SyncRoot)
{
return new SynchronizedDictionaryEnumerator(SyncRoot, _table.GetEnumerator());
}
}
///<summary>
///Removes the element with the specified key from the <see cref="T:System.Collections.IDictionary"></see> object.
///</summary>
///<param name="key">The key of the element to remove. </param>
///<exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IDictionary"></see> object is read-only.-or- The <see cref="T:System.Collections.IDictionary"></see> has a fixed size. </exception>
///<exception cref="T:System.ArgumentNullException">key is null. </exception><filterpriority>2</filterpriority>
public void Remove(object key)
{
lock (SyncRoot)
{
_table.Remove(key);
}
}
#endregion
#region IEnumerable implementation
///<summary>
///Returns an enumerator that iterates through a collection.
///</summary>
///<returns>
///An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection.
///</returns>
IEnumerator IEnumerable.GetEnumerator()
{
lock (SyncRoot)
{
return new SynchronizedEnumerator(SyncRoot, ((IEnumerable)_table).GetEnumerator());
}
}
#endregion
#region Indexer
///<summary>
///Gets or sets the element with the specified key.
///</summary>
///<returns>
///The element with the specified key.
///</returns>
///<param name="key">The key of the element to get or set. </param>
///<exception cref="T:System.NotSupportedException">The property is set and the <see cref="T:System.Collections.IDictionary"></see> object is read-only.-or- The property is set, key does not exist in the collection, and the <see cref="T:System.Collections.IDictionary"></see> has a fixed size. </exception>
///<exception cref="T:System.ArgumentNullException">key is null. </exception><filterpriority>2</filterpriority>
public object this[object key]
{
get
{
lock (SyncRoot)
{
return _table[key];
}
}
set
{
lock (SyncRoot)
{
_table[key] = value;
}
}
}
#endregion
}
}

View File

@@ -180,7 +180,7 @@ namespace Spring.Expressions
private static ConstructorInfo[] GetCandidateConstructors(Type type, int argCount)
{
ConstructorInfo[] ctors = type.GetConstructors();
ConstructorInfo[] ctors = type.GetConstructors(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
ArrayList matches = new ArrayList();
foreach (ConstructorInfo ctor in ctors)

View File

@@ -410,11 +410,12 @@ namespace Spring.Objects.Factory
public static string TransformedObjectName(string name)
{
AssertUtils.ArgumentNotNull(name, "name", "Object name must not be null.");
string objectName = name;
if (ObjectFactoryUtils.IsFactoryDereference(objectName))
if (!ObjectFactoryUtils.IsFactoryDereference(name))
{
objectName = objectName.Substring(ObjectFactoryUtils.FactoryObjectPrefix.Length);
return name;
}
string objectName = name.Substring(ObjectFactoryUtils.FactoryObjectPrefix.Length);
return objectName;
}
@@ -459,8 +460,10 @@ namespace Spring.Objects.Factory
public static bool IsFactoryDereference(string name)
{
return name != null
&& name.Length > ObjectFactoryUtils.FactoryObjectPrefix.Length
&& name[0] == ObjectFactoryUtils.FactoryObjectPrefix[0]
&& name.StartsWith(ObjectFactoryUtils.FactoryObjectPrefix)
&& name.Length > ObjectFactoryUtils.FactoryObjectPrefix.Length;
;
}
}
}

View File

@@ -162,6 +162,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Collections\CaseInsensitiveHashtable.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Collections\DictionarySet.cs"
SubType = "Code"

View File

@@ -103,6 +103,7 @@
<Compile Include="Collections\AbstractQueue.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Collections\CaseInsensitiveHashtable.cs" />
<Compile Include="Collections\DictionarySet.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -1,143 +1,144 @@
#region License
/*
* Copyright <20> 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
#endregion
namespace Spring.Util
{
/// <summary>
/// Use this class for obtaining <see cref="ModuleBuilder"/> instances for dynamic code generation.
/// </summary>
/// <remarks>
/// <p>
/// The purpose of this class is to provide a simple abstraction for creating and managing dynamic assemblies.
/// </p>
/// <note>
/// Using this factory you can't define several modules within a single dynamic assembly - only a simple one2one relation between assembly/module is used.
/// </note>
/// </remarks>
/// <example>
/// <p>The following excerpt from <see cref="Spring.Proxy.DynamicProxyManager"/> demonstrates usage:</p>
/// <code language="c#">
/// public class DynamicProxyManager
/// {
/// public const string PROXY_ASSEMBLY_NAME = "Spring.Proxy";
///
/// public static TypeBuilder CreateTypeBuilder(string name, Type baseType)
/// {
/// // Generates type name
/// string typeName = String.Format("{0}.{1}_{2}", PROXY_ASSEMBLY_NAME, name, Guid.NewGuid().ToString("N"));
/// ModuleBuilder module = DynamicCodeManager.GetModuleBuilder(PROXY_ASSEMBLY_NAME);
/// return module.DefineType(typeName, PROXY_TYPE_ATTRIBUTES);
/// }
/// }
/// </code>
/// </example>
/// <author>Erich Eichinger</author>
/// <seealso cref="Spring.Reflection.Dynamic.DynamicReflectionManager"/>
/// <seealso cref="Spring.Proxy.DynamicProxyManager"/>
/// <seealso cref="Spring.Objects.Factory.Support.MethodInjectingInstantiationStrategy"/>
public sealed class DynamicCodeManager
{
private static readonly Hashtable s_moduleCache = CollectionsUtil.CreateCaseInsensitiveHashtable();
/// <summary>
/// prevent instantiation
/// </summary>
private DynamicCodeManager()
{
throw new InvalidOperationException();
}
/// <summary>
/// Returns the <see cref="ModuleBuilder"/> for the dynamic module within the specified assembly.
/// </summary>
/// <remarks>
/// If the assembly does not exist yet, it will be created.<br/>
/// This factory caches any dynamic assembly it creates - calling GetModule() twice with
/// the same name will *not* create 2 distinct modules!
/// </remarks>
/// <param name="assemblyName">The assembly-name of the module to be returned</param>
/// <returns>the <see cref="ModuleBuilder"/> that can be used to define new types within the specified assembly</returns>
public static ModuleBuilder GetModuleBuilder( string assemblyName )
{
lock(s_moduleCache.SyncRoot)
{
ModuleBuilder module = (ModuleBuilder) s_moduleCache[assemblyName];
if (module == null)
{
AssemblyName an = new AssemblyName();
an.Name = assemblyName;
AssemblyBuilder assembly;
#if DEBUG_DYNAMIC
assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave, null, null, null, null,null, true );
module = assembly.DefineDynamicModule(an.Name, an.Name + ".dll", true);
#else
assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run, null, null, null, null,null, true );
#if DEBUG
module = assembly.DefineDynamicModule(an.Name, true);
#else
module = assembly.DefineDynamicModule(an.Name, false);
#endif
#endif
s_moduleCache[assemblyName] = module;
}
return module;
}
}
/// <summary>
/// Persists the specified dynamic assembly to the file-system
/// </summary>
/// <param name="assemblyName">the name of the dynamic assembly to persist</param>
/// <remarks>
/// Can only be called in DEBUG_DYNAMIC mode, per ConditionalAttribute rules.
/// </remarks>
[Conditional("DEBUG_DYNAMIC")]
public static void SaveAssembly( string assemblyName )
{
AssertUtils.ArgumentHasText(assemblyName, "assemblyName");
ModuleBuilder module = null;
lock(s_moduleCache.SyncRoot)
{
module = (ModuleBuilder) s_moduleCache[assemblyName];
}
if(module == null)
{
throw new ArgumentException(string.Format("'{0}' is not a valid dynamic assembly name", assemblyName), "assemblyName");
}
AssemblyBuilder assembly = (AssemblyBuilder) module.Assembly;
assembly.Save(assembly.GetName().Name + ".dll");
}
}
#region License
/*
* Copyright <20> 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using Spring.Collections;
#endregion
namespace Spring.Util
{
/// <summary>
/// Use this class for obtaining <see cref="ModuleBuilder"/> instances for dynamic code generation.
/// </summary>
/// <remarks>
/// <p>
/// The purpose of this class is to provide a simple abstraction for creating and managing dynamic assemblies.
/// </p>
/// <note>
/// Using this factory you can't define several modules within a single dynamic assembly - only a simple one2one relation between assembly/module is used.
/// </note>
/// </remarks>
/// <example>
/// <p>The following excerpt from <see cref="Spring.Proxy.DynamicProxyManager"/> demonstrates usage:</p>
/// <code language="c#">
/// public class DynamicProxyManager
/// {
/// public const string PROXY_ASSEMBLY_NAME = "Spring.Proxy";
///
/// public static TypeBuilder CreateTypeBuilder(string name, Type baseType)
/// {
/// // Generates type name
/// string typeName = String.Format("{0}.{1}_{2}", PROXY_ASSEMBLY_NAME, name, Guid.NewGuid().ToString("N"));
/// ModuleBuilder module = DynamicCodeManager.GetModuleBuilder(PROXY_ASSEMBLY_NAME);
/// return module.DefineType(typeName, PROXY_TYPE_ATTRIBUTES);
/// }
/// }
/// </code>
/// </example>
/// <author>Erich Eichinger</author>
/// <seealso cref="Spring.Reflection.Dynamic.DynamicReflectionManager"/>
/// <seealso cref="Spring.Proxy.DynamicProxyManager"/>
/// <seealso cref="Spring.Objects.Factory.Support.MethodInjectingInstantiationStrategy"/>
public sealed class DynamicCodeManager
{
private static readonly Hashtable s_moduleCache = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
/// <summary>
/// prevent instantiation
/// </summary>
private DynamicCodeManager()
{
throw new InvalidOperationException();
}
/// <summary>
/// Returns the <see cref="ModuleBuilder"/> for the dynamic module within the specified assembly.
/// </summary>
/// <remarks>
/// If the assembly does not exist yet, it will be created.<br/>
/// This factory caches any dynamic assembly it creates - calling GetModule() twice with
/// the same name will *not* create 2 distinct modules!
/// </remarks>
/// <param name="assemblyName">The assembly-name of the module to be returned</param>
/// <returns>the <see cref="ModuleBuilder"/> that can be used to define new types within the specified assembly</returns>
public static ModuleBuilder GetModuleBuilder( string assemblyName )
{
lock(s_moduleCache.SyncRoot)
{
ModuleBuilder module = (ModuleBuilder) s_moduleCache[assemblyName];
if (module == null)
{
AssemblyName an = new AssemblyName();
an.Name = assemblyName;
AssemblyBuilder assembly;
#if DEBUG_DYNAMIC
assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave, null, null, null, null,null, true );
module = assembly.DefineDynamicModule(an.Name, an.Name + ".dll", true);
#else
assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run, null, null, null, null,null, true );
#if DEBUG
module = assembly.DefineDynamicModule(an.Name, true);
#else
module = assembly.DefineDynamicModule(an.Name, false);
#endif
#endif
s_moduleCache[assemblyName] = module;
}
return module;
}
}
/// <summary>
/// Persists the specified dynamic assembly to the file-system
/// </summary>
/// <param name="assemblyName">the name of the dynamic assembly to persist</param>
/// <remarks>
/// Can only be called in DEBUG_DYNAMIC mode, per ConditionalAttribute rules.
/// </remarks>
[Conditional("DEBUG_DYNAMIC")]
public static void SaveAssembly( string assemblyName )
{
AssertUtils.ArgumentHasText(assemblyName, "assemblyName");
ModuleBuilder module = null;
lock(s_moduleCache.SyncRoot)
{
module = (ModuleBuilder) s_moduleCache[assemblyName];
}
if(module == null)
{
throw new ArgumentException(string.Format("'{0}' is not a valid dynamic assembly name", assemblyName), "assemblyName");
}
AssemblyBuilder assembly = (AssemblyBuilder) module.Assembly;
assembly.Save(assembly.GetName().Name + ".dll");
}
}
}

View File

@@ -506,6 +506,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Generic\DataAdapterDelegate.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Generic\IAdoOperations.cs"
SubType = "Code"
@@ -516,6 +521,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Generic\IDataAdapterCallback.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Generic\IDbCommandCallback.cs"
SubType = "Code"
@@ -656,6 +666,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Support\DefaultTransactionScopeAdapter.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Support\ErrorCodeExceptionTranslator.cs"
SubType = "Code"
@@ -676,6 +691,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Support\ITransactionScopeAdapter.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Support\NamedResultSetProcessor.cs"
SubType = "Code"
@@ -949,6 +969,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Transaction\Support\IResourceTransactionManager.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Transaction\Support\ISmartTransactionObject.cs"
SubType = "Code"

View File

@@ -28,6 +28,7 @@ using System.Reflection;
using System.Web;
using System.Web.Hosting;
using Common.Logging;
using Spring.Collections;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.Util;
@@ -126,7 +127,7 @@ namespace Spring.Context.Support
/// Since the HttpRuntime discards it's configurationsection cache, we maintain our own context cache.
/// Despite it really speeds up context-lookup, since we don't have to go through the whole HttpConfigurationSystem
/// </summary>
private static readonly Hashtable s_webContextCache = CollectionsUtil.CreateCaseInsensitiveHashtable();
private static readonly Hashtable s_webContextCache = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
static WebApplicationContext()
{

View File

@@ -27,6 +27,7 @@ using System.Web;
using System.Web.Caching;
using System.Web.SessionState;
using Common.Logging;
using Spring.Collections;
using Spring.Context.Support;
using Spring.Objects.Factory.Config;
using Spring.Util;
@@ -50,6 +51,7 @@ namespace Spring.Objects.Factory.Support
{
private readonly static ILog log = LogManager.GetLogger(typeof(WebObjectFactory));
private static bool s_eventHandlersRegistered = false;
private readonly static string OBJECTTABLEKEY = "spring.objects";
private delegate IDictionary ObjectDictionaryCreationHandler();
@@ -68,7 +70,7 @@ namespace Spring.Objects.Factory.Support
static WebObjectFactory()
{
EnsureEventHandlersRegistered();
//EnsureEventHandlersRegistered();
}
/// <summary>
@@ -77,9 +79,19 @@ namespace Spring.Objects.Factory.Support
/// </summary>
private static void EnsureEventHandlersRegistered()
{
if (log.IsDebugEnabled) log.Debug("hooking up event handlers");
VirtualEnvironment.EndRequest += new VirtualEnvironment.RequestEventHandler(OnEndRequest);
VirtualEnvironment.EndSession += new VirtualEnvironment.SessionEventHandler(OnEndSession);
if (!s_eventHandlersRegistered)
{
lock(typeof(WebObjectFactory))
{
if (s_eventHandlersRegistered) return;
if (log.IsDebugEnabled) log.Debug("hooking up event handlers");
VirtualEnvironment.EndRequest += new VirtualEnvironment.RequestEventHandler(OnEndRequest);
VirtualEnvironment.EndSession += new VirtualEnvironment.SessionEventHandler(OnEndSession);
s_eventHandlersRegistered = true;
}
}
}
/// <summary>
@@ -303,6 +315,8 @@ namespace Spring.Objects.Factory.Support
object instance;
lock (scopedSingletonCache.SyncRoot)
{
EnsureEventHandlersRegistered();
instance = scopedSingletonCache[objectName];
if (instance == TemporarySingletonPlaceHolder)
{
@@ -397,23 +411,26 @@ namespace Spring.Objects.Factory.Support
}
/// <summary>
/// Injects dependencies into the supplied <paramref name="target"/> instance
/// using the named object definition.
/// Configures object instance by injecting dependencies, satisfying Spring lifecycle
/// interfaces and applying object post-processors.
/// </summary>
/// <param name="target">
/// The object instance that is to be so configured.
/// </param>
/// <param name="name">
/// The name of the object definition expressing the dependencies that are to
/// be injected into the supplied <parameref name="target"/> instance.
/// </param>
/// <param name="definition">
/// An object definition that should be used to configure object.
/// </param>
/// <param name="wrapper">
/// A wrapped object instance that is to be so configured.
/// </param>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.ConfigureObject(object, string)"/>
public override object ConfigureObject(object target, string name)
protected override object ConfigureObject(string name, RootObjectDefinition definition, IObjectWrapper wrapper)
{
// always configure object relative to contextPath
using (new HttpContextSwitch(contextPath))
{
return base.ConfigureObject(target, name);
return base.ConfigureObject(name, definition, wrapper);
}
}
@@ -482,7 +499,7 @@ namespace Spring.Objects.Factory.Support
/// </summary>
private static IDictionary CreateCaseInsensitiveDictionary()
{
return CollectionsUtil.CreateCaseInsensitiveHashtable();
return new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
}
/// <summary>

View File

@@ -275,6 +275,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Util\ISessionState.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Util\IVirtualEnvironment.cs"
SubType = "Code"

View File

@@ -122,6 +122,7 @@
<Compile Include="Globalization\AspNetResourceCache.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Util\ISessionState.cs" />
<Compile Include="Web\UI\IValidationContainer.cs" />
<Compile Include="Web\Support\MimeMediaType.cs" />
<Compile Include="Web\Support\SharedStateResourceCache.cs">

View File

@@ -0,0 +1,48 @@
using System.Collections;
using System.Web;
using System.Web.SessionState;
namespace Spring.Util
{
/// <summary>
/// Abstracts HttpSession
/// </summary>
public interface ISessionState : IDictionary
{
/// <summary>
/// <see cref="System.Web.SessionState.HttpSessionState.Abandon"/>
/// </summary>
void Abandon();
/// <summary>
/// <see cref="System.Web.SessionState.HttpSessionState.IsCookieless"/>
/// </summary>
bool IsCookieless { get; }
/// <summary>
/// <see cref="System.Web.SessionState.HttpSessionState.IsNewSession"/>
/// </summary>
bool IsNewSession { get; }
/// <summary>
/// <see cref="System.Web.SessionState.HttpSessionState.LCID"/>
/// </summary>
int LCID { get; set; }
/// <summary>
/// <see cref="System.Web.SessionState.HttpSessionState.Mode"/>
/// </summary>
SessionStateMode Mode { get; }
/// <summary>
/// <see cref="System.Web.SessionState.HttpSessionState.SessionID"/>
/// </summary>
string SessionID { get; }
/// <summary>
/// <see cref="System.Web.SessionState.HttpSessionState.CodePage"/>
/// </summary>
int CodePage { get; set; }
#if NET_2_0
/// <summary>
/// <see cref="System.Web.SessionState.HttpSessionState.CookieMode"/>
/// </summary>
HttpCookieMode CookieMode { get; }
#endif
}
}

View File

@@ -21,6 +21,7 @@
#region Imports
using System;
using System.Collections;
using System.Globalization;
using System.Reflection;
using System.Web;
@@ -66,5 +67,14 @@ namespace Spring.Util
/// Maps a virtual path to it's physical location
/// </summary>
string MapPath( string virtualPath );
/// <summary>
/// Returns the current Session's variable dictionary
/// </summary>
ISessionState Session { get; }
/// <summary>
/// Returns the current Request's variable dictionary
/// </summary>
IDictionary RequestVariables { get; }
}
}

View File

@@ -21,6 +21,7 @@
#region Imports
using System;
using System.Collections;
using System.IO;
using System.Web;
using System.Web.Caching;
@@ -71,16 +72,167 @@ namespace Spring.Util
return prevEnvironment;
}
#region default IVirtualEnvironment Adapter for HttpRuntime
#region default IVirtualEnvironment Adapter for HttpRuntime
/// <summary>
/// Implementation for running within HttpRuntime
/// </summary>
private class HttpRuntimeEnvironment : IVirtualEnvironment
{
#region HttpSessionState Adapter
private class SessionDictionaryAdapter : ISessionState
{
private readonly HttpSessionState _sessionState;
public SessionDictionaryAdapter(HttpSessionState sessionState)
{
_sessionState = sessionState;
}
public bool Contains(object key)
{
ICollection keys = _sessionState.Keys;
foreach (string sessionKey in keys)
{
if (object.Equals(sessionKey, (string)key)) return true;
}
return false;
}
public void Add(object key, object value)
{
_sessionState.Add((string)key, value);
}
public void Clear()
{
_sessionState.Clear();
}
public IDictionaryEnumerator GetEnumerator()
{
Hashtable tableCopy = new Hashtable();
ICollection keys = _sessionState.Keys;
foreach (string sessionKey in keys)
{
tableCopy.Add(sessionKey, _sessionState[sessionKey]);
}
return tableCopy.GetEnumerator();
}
public void Remove(object key)
{
_sessionState.Remove((string) key);
}
public object this[object key]
{
get { return _sessionState[(string)key]; }
set { _sessionState[(string)key] = value; }
}
public ICollection Keys
{
get { return _sessionState.Keys; }
}
public ICollection Values
{
get
{
object[] values = new object[_sessionState.Count];
_sessionState.CopyTo(values, 0);
return values;
}
}
public bool IsReadOnly
{
get { return _sessionState.IsReadOnly; }
}
public bool IsFixedSize
{
get { return false; }
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void CopyTo(Array array, int index)
{
_sessionState.CopyTo(array, index);
}
public int Count
{
get { return _sessionState.Count; }
}
public object SyncRoot
{
get { return _sessionState.SyncRoot; }
}
public bool IsSynchronized
{
get { return _sessionState.IsSynchronized; }
}
public void Abandon()
{
_sessionState.Abandon();
}
public bool IsCookieless
{
get { return _sessionState.IsCookieless; }
}
public bool IsNewSession
{
get { return _sessionState.IsNewSession; }
}
public int LCID
{
get { return _sessionState.LCID; }
set { _sessionState.LCID = value; }
}
public SessionStateMode Mode
{
get { return _sessionState.Mode; }
}
public string SessionID
{
get { return _sessionState.SessionID; }
}
public int CodePage
{
get { return _sessionState.CodePage; }
set { _sessionState.CodePage = value; }
}
#if NET_2_0
public HttpCookieMode CookieMode
{
get { return _sessionState.CookieMode; }
}
#endif
}
#endregion //HttpSessionState Adapter
public string ApplicationVirtualPath
{
get {
get
{
string appPath = HttpRuntime.AppDomainAppVirtualPath;
if (!appPath.EndsWith("/")) appPath = appPath + "/";
return appPath;
@@ -124,6 +276,16 @@ namespace Spring.Util
#endif
throw new ArgumentException("can't map context relative path outside a context");
}
public ISessionState Session
{
get { return new SessionDictionaryAdapter(HttpContext.Current.Session); }
}
public IDictionary RequestVariables
{
get { return HttpContext.Current.Items; }
}
}
#endregion

View File

@@ -25,6 +25,7 @@ using System.Collections;
using System.Collections.Specialized;
using System.Web;
using System.Web.SessionState;
using Spring.Collections;
using Spring.Context;
using Spring.Util;
using Spring.Web.Process;
@@ -52,7 +53,7 @@ namespace Spring.Web.Support
private object controller;
private string defaultView;
private string currentView;
private IDictionary views = CollectionsUtil.CreateCaseInsensitiveHashtable();
private IDictionary views = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
private IDictionary sharedState;
private IApplicationContext applicationContext;
private string processUrl;

View File

@@ -70,7 +70,7 @@ namespace Spring.Web.Support
{
private readonly ILog Log = LogManager.GetLogger(typeof(PageHandlerFactory));
private readonly IDictionary pageHandlerWrappers = CollectionsUtil.CreateCaseInsensitiveHashtable();
private readonly IDictionary pageHandlerWrappers = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
/// <summary>
/// Retrieves instance of the configured page from Spring web application context,

View File

@@ -0,0 +1,116 @@
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using NUnit.Framework;
#endregion
namespace Spring.Collections
{
/// <summary>
///
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class CaseInsensitiveHashtableTests
{
[Test]
public void IgnoresCase()
{
CaseInsensitiveHashtable st = new CaseInsensitiveHashtable();
st.Add("key", "value");
Assert.AreEqual("value", st["KEY"]);
st["KeY"] = "value2";
Assert.AreEqual(1, st.Count);
Assert.AreEqual("value2", st["key"]);
try
{
st.Add("KEY", "value2");
Assert.Fail();
}
catch (ArgumentException)
{}
Hashtable ht = new Hashtable();
ht.Add("key","value");
ht.Add("KEY","value");
try
{
st = new CaseInsensitiveHashtable(ht, CultureInfo.InvariantCulture);
Assert.Fail();
}
catch (ArgumentException)
{}
}
[Test]
public void InitializeFromOtherCopiesValues()
{
Hashtable ht = new Hashtable();
ht["key"] = "value";
ht["key2"] = "value2";
CaseInsensitiveHashtable st = new CaseInsensitiveHashtable(ht, CultureInfo.InvariantCulture);
Assert.AreEqual(2, st.Count);
ht.Remove("key");
Assert.AreEqual(1, ht.Count);
Assert.AreEqual(2, st.Count);
}
/// <summary>
/// On my NB gives
/// Duration: 00:00:11.0937500
/// Duration: 00:00:05.3593750
/// </summary>
[Test, Explicit]
public void ComparePerformance()
{
const int runs = 30000000;
StopWatch watch = new StopWatch();
Hashtable ht = CollectionsUtil.CreateCaseInsensitiveHashtable();
for(int i=0;i<1000000;i++) ht.Add(Guid.NewGuid().ToString(), "val"); // gen. higher number of elements results in OOM exception????
CaseInsensitiveHashtable ciht = new CaseInsensitiveHashtable(ht, CultureInfo.InvariantCulture);
using (watch.Start("Duration: {0}"))
{
for (int i = 0; i < runs; i++)
{
object v = ht["somekey"];
}
}
using (watch.Start("Duration: {0}"))
{
for (int i = 0; i < runs; i++)
{
object v = ciht["somekey"];
}
}
}
}
}

View File

@@ -37,10 +37,100 @@ namespace Spring.Collections
[TestFixture]
public class SynchronizedHashtableTests
{
[Test]
public void BehavesLikeHashtable()
{
SynchronizedHashtable st = new SynchronizedHashtable();
st.Add("key", "value");
Assert.AreEqual("value", st["key"]);
st["key"] = "value2";
Assert.AreEqual("value2", st["key"]);
st["key2"] = "value3";
Assert.AreEqual("value3", st["key2"]);
try
{
st.Add("key", "value4");
Assert.Fail();
}
catch(ArgumentException)
{}
Assert.AreEqual(2, st.Count);
}
[Test]
public void InitializeFromOtherCopiesValues()
{
Hashtable ht = new Hashtable();
ht["key"] = "value";
ht["key2"] = "value2";
SynchronizedHashtable st = new SynchronizedHashtable(ht, false);
Assert.AreEqual(2, st.Count);
ht.Remove("key");
Assert.AreEqual(1, ht.Count);
Assert.AreEqual(2, st.Count);
}
[Test]
public void DefaultsToCaseSensitive()
{
SynchronizedHashtable st = new SynchronizedHashtable();
st.Add("key","value");
st.Add("KEY","value");
Assert.AreEqual(2, st.Count);
}
[Test]
public void IgnoreCaseIgnoresCase()
{
SynchronizedHashtable st = new SynchronizedHashtable(true);
st.Add("key", "value");
Assert.AreEqual("value", st["KEY"]);
st["KeY"] = "value2";
Assert.AreEqual(1, st.Count);
Assert.AreEqual("value2", st["key"]);
try
{
st.Add("KEY", "value2");
Assert.Fail();
}
catch (ArgumentException)
{}
Hashtable ht = new Hashtable();
ht.Add("key","value");
ht.Add("KEY","value");
try
{
st = new SynchronizedHashtable(ht, true);
Assert.Fail();
}
catch (ArgumentException)
{}
}
[Test]
public void WrapKeepsOriginalHashtableReference()
{
Hashtable ht = new Hashtable();
ht["key"] = "value";
ht["key2"] = "value2";
SynchronizedHashtable st = SynchronizedHashtable.Wrap(ht);
Assert.AreEqual(2, st.Count);
ht.Remove("key");
Assert.AreEqual(1, ht.Count);
Assert.AreEqual(1, st.Count);
}
/// <summary>
/// On my Notebook gives
/// Normal Hashtable: 00:00:01.5937500
/// Synced Hashtable: 00:00:02.8593750
/// Normal Hashtable: 00:00:00.0937500
/// Synced Hashtable: 00:00:00.9375000
/// =locking *has* a peformance impact.
/// </summary>
[Test, Explicit]
public void TestLockingPerformanceImpact()

View File

@@ -0,0 +1,112 @@
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using NUnit.Framework;
#endregion
namespace Spring.Expressions
{
/// <summary>
///
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class ConstructorNodeTests
{
#region Test Classes
public class PublicTestClass
{
public string _s;
public int _i;
public PublicTestClass(string s)
:this(s, -1)
{}
protected PublicTestClass(string s, int i)
{
_s = s; _i=i;
}
}
private class PrivateTestClass : PublicTestClass
{
private PrivateTestClass(string s, int i)
:base(s,i)
{
}
}
#endregion Test Classes
[Test]
public void CanCreatePublicInstance()
{
ConstructorNode ctorNode = new ConstructorNode();
ctorNode.Text=typeof(PublicTestClass).FullName;
StringLiteralNode sNode = new StringLiteralNode();
sNode.Text = "theValue";
ctorNode.addChild(sNode);
PublicTestClass instance = (PublicTestClass) ((IExpression)ctorNode).GetValue();
Assert.AreEqual( sNode.Text, instance._s );
Assert.AreEqual( -1, instance._i );
}
[Test]
public void CanCreatePublicInstanceWithNonPublicConstructor()
{
ConstructorNode ctorNode = new ConstructorNode();
ctorNode.Text=typeof(PublicTestClass).FullName;
StringLiteralNode sNode = new StringLiteralNode();
sNode.Text = "theValue2";
ctorNode.addChild(sNode);
IntLiteralNode iNode = new IntLiteralNode();
iNode.Text="2";
ctorNode.addChild(iNode);
PublicTestClass instance = (PublicTestClass) ((IExpression)ctorNode).GetValue();
Assert.AreEqual( sNode.Text, instance._s );
Assert.AreEqual( 2, instance._i );
}
[Test]
public void CanCreateNonPublicInstanceWithNonPublicConstructor()
{
ConstructorNode ctorNode = new ConstructorNode();
ctorNode.Text=typeof(PrivateTestClass).FullName;
StringLiteralNode sNode = new StringLiteralNode();
sNode.Text = "theValue3";
ctorNode.addChild(sNode);
IntLiteralNode iNode = new IntLiteralNode();
iNode.Text="3";
ctorNode.addChild(iNode);
PublicTestClass instance = (PublicTestClass) ((IExpression)ctorNode).GetValue();
Assert.AreEqual( sNode.Text, instance._s );
Assert.AreEqual( 3, instance._i );
}
}
}

View File

@@ -22,12 +22,51 @@
using System;
using NUnit.Framework;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
#endregion
namespace Spring.Objects.Factory
{
public class TestAbstractObjectFactory : AbstractObjectFactory
{
protected override object CreateObject(string name, RootObjectDefinition definition, object[] arguments)
{
throw new System.NotImplementedException();
}
protected override void DestroyObject(string name, object target)
{
throw new System.NotImplementedException();
}
public override bool ContainsObjectDefinition(string name)
{
throw new System.NotImplementedException();
}
public override IObjectDefinition GetObjectDefinition(string name)
{
throw new System.NotImplementedException();
}
public override IObjectDefinition GetObjectDefinition(string name, bool includeAncestors)
{
throw new System.NotImplementedException();
}
public override object ConfigureObject(object target, string name)
{
throw new System.NotImplementedException();
}
public override object ConfigureObject(object target, string name, IObjectDefinition definition)
{
throw new System.NotImplementedException();
}
}
/// <summary>
/// Subclasses must override SetUp () to initialize the object factory
/// and any other variables they need.
@@ -38,13 +77,43 @@ namespace Spring.Objects.Factory
{
#region Properties
protected internal abstract IObjectFactory ObjectFactory { get; }
protected internal abstract AbstractObjectFactory CreateObjectFactory(bool caseSensitive);
#endregion
protected AbstractObjectFactory ObjectFactory { get { return CreateObjectFactory(true); } }
#endregion
#region Tests
#region Case Insensitive Tests
/// <summary>
[Test]
public void RespectsCaseInsensitiveNamesAndAliases()
{
AbstractObjectFactory of = CreateObjectFactory(false);
object testObject = new object();
of.RegisterSingleton("name", testObject);
of.RegisterAlias("NAME", "alias");
try
{
of.RegisterAlias("NaMe", "AlIaS");
Assert.Fail();
}
catch (ObjectDefinitionStoreException ex)
{
Assert.IsTrue( -1<ex.Message.IndexOf("already registered") );
}
Assert.AreEqual(1, of.GetAliases("nAmE").Length);
Assert.AreEqual(testObject, of.GetObject("nAmE"));
Assert.AreEqual(testObject, of.GetObject("ALIAS"));
}
#endregion
#region Tests
/// <summary>
/// Roderick objects inherits from rod, overriding name only.
/// </summary>
[Test]

View File

@@ -69,9 +69,11 @@ namespace Spring.Objects.Factory.Xml
#endregion
protected internal override IObjectFactory ObjectFactory
protected internal override AbstractObjectFactory CreateObjectFactory(bool caseSensitive)
{
get { return factory; }
return (caseSensitive)
? factory
: new DefaultListableObjectFactory(caseSensitive);
}
private DefaultListableObjectFactory parent;

View File

@@ -252,6 +252,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Collections\SynchronizedHashtableTests.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Context\ApplicationEventArgsTests.cs"
SubType = "Code"

View File

@@ -118,6 +118,7 @@
<Compile Include="Collections\AbstractQueueTests.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Collections\CaseInsensitiveHashtableTests.cs" />
<Compile Include="Collections\HashedSetTests.cs">
<SubType>Code</SubType>
</Compile>
@@ -270,6 +271,7 @@
<Compile Include="ExceptionsTest.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Expressions\ConstructorNodeTests.cs" />
<Compile Include="Expressions\ExpressionEvaluatorTests.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -140,6 +140,11 @@
HintPath = "..\..\..\lib\Net\1.1\nunit.core.interfaces.dll"
Private = "False"
/>
<Reference
Name = "antlr.runtime"
AssemblyName = "antlr.runtime"
HintPath = "..\..\..\lib\Net\1.1\antlr.runtime.dll"
/>
</References>
</Build>
<Files>
@@ -172,11 +177,24 @@
RelPath = "Context\Support\HttpApplicationConfigurerTests.xml"
BuildAction = "EmbeddedResource"
/>
<File
RelPath = "Context\Support\WebApplicationContextTests.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Core\IO\WebResourceTests.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Data\Spring\Context\Support\WebApplicationContextTests\Dummy.aspx"
BuildAction = "Content"
/>
<File
RelPath = "Data\Spring\Context\Support\WebApplicationContextTests\Web.Config"
BuildAction = "None"
/>
<File
RelPath = "Data\Spring\Objects\Factory\Support\TestForm.aspx"
BuildAction = "Content"
@@ -208,7 +226,7 @@
BuildAction = "Content"
/>
<File
RelPath = "Data\Spring\Web\Support\PageHandlerFactoryTests\Web.Config"
RelPath = "Data\Spring\Web\Support\PageHandlerFactoryTests\Web.Config.net-1.1"
BuildAction = "None"
/>
<File
@@ -231,6 +249,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "TestSupport\SessionMock.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "TestSupport\TestPage.cs"
SubType = "ASPXCodeBehind"
@@ -268,7 +291,7 @@
/>
<File
RelPath = "Util\ControlInterceptionTests.cs"
SubType = "Code"
SubType = "ASPXCodeBehind"
BuildAction = "Compile"
/>
<File

View File

@@ -88,6 +88,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="TestSupport\NUnitAdapter.cs" />
<Compile Include="TestSupport\SessionMock.cs" />
<Compile Include="TestSupport\TestPage.cs">
<SubType>ASPXCodeBehind</SubType>
</Compile>

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections;
using System.Web;
using System.Web.SessionState;
using Spring.Util;
namespace Spring.TestSupport
{
/// <summary>
/// Test Session implementation
/// </summary>
public class SessionMock : Hashtable, ISessionState
{
private bool _isCookieless;
private bool _isNewSession;
private int _lcid;
private SessionStateMode _mode;
private string _sessionID;
private int _codePage;
#if NET_2_0
private HttpCookieMode _cookieMode;
#endif
public SessionMock() : base(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default)
{
Reset();
}
protected virtual void Reset()
{
_sessionID = Guid.NewGuid().ToString();
_isNewSession = false;
_isCookieless = false;
_mode = SessionStateMode.InProc;
_codePage = -1;
#if NET_2_0
_cookieMode = HttpCookieMode.AutoDetect;
#endif
}
public void Abandon()
{
Reset();
}
public bool IsCookieless
{
get { return _isCookieless; }
set { _isCookieless = value; }
}
public bool IsNewSession
{
get { return _isNewSession; }
set { _isNewSession = value; }
}
public int LCID
{
get { return _lcid; }
set { _lcid = value; }
}
public SessionStateMode Mode
{
get { return _mode; }
set { _mode = value; }
}
public string SessionID
{
get { return _sessionID; }
set { _sessionID = value; }
}
public int CodePage
{
get { return _codePage; }
set { _codePage = value; }
}
#if NET_2_0
public HttpCookieMode CookieMode
{
get { return _cookieMode; }
set { _cookieMode = value; }
}
#endif
}
}

View File

@@ -5,6 +5,7 @@ using System.IO;
using System.Reflection;
using System.Web;
using System.Web.UI;
using Spring.Collections;
using Page=Spring.Web.UI.Page;
namespace Spring.TestSupport
@@ -13,7 +14,7 @@ namespace Spring.TestSupport
{
public TestPage()
{
this.SharedState = CollectionsUtil.CreateCaseInsensitiveHashtable();
this.SharedState = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
}
public TestPage( HttpContext context )

View File

@@ -21,11 +21,16 @@
#region Imports
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Web;
using System.Web.Hosting;
using Spring.Collections;
using Spring.Expressions;
using Spring.Reflection.Dynamic;
#endregion
@@ -35,7 +40,8 @@ namespace Spring.TestSupport
{
private readonly TextWriter _out;
private readonly HttpWorkerRequest _wr;
[ThreadStatic] private static TestWebContext _wc;
[ThreadStatic]
private static TestWebContext _wc;
public static void Create(string virtualPath, string page)
{
@@ -54,24 +60,34 @@ namespace Spring.TestSupport
{
_out = new StringWriter();
HttpWorkerRequest wr;
object appPath = Thread.GetDomain().GetData(".appPath");
AppDomain domain = Thread.GetDomain();
// are we running within a valid AspNet AppDomain?
string appPath = (string) domain.GetData(".appPath");
if (appPath != null)
{
wr = new SimpleWorkerRequest(page, string.Empty, _out);
}
else
{
string physDir = AppDomain.CurrentDomain.BaseDirectory + "\\";
wr = new SimpleWorkerRequest(virtualPath, physDir, page, string.Empty, _out);
appPath = domain.BaseDirectory + "\\";
wr = new SimpleWorkerRequest(virtualPath, appPath, page, string.Empty, _out);
}
HttpContext ctx = new HttpContext(wr);
HttpContext.Current = ctx;
HttpBrowserCapabilities browser = new HttpBrowserCapabilities();
#if NET_2_0
browser.Capabilities = CollectionsUtil.CreateCaseInsensitiveHashtable();
browser.Capabilities = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
browser.Capabilities[string.Empty] = "Test User Agent"; // string.Empty is the key for "user agent"
// avoids NullReferenceException when accessing HttpRequest.FilePath
object virtualPathObject = ExpressionEvaluator.GetValue(null, "T(System.Web.VirtualPath).Create('/')");
object cachedPathData = ExpressionEvaluator.GetValue(null, "T(System.Web.CachedPathData).GetRootWebPathData()");
ExpressionEvaluator.SetValue(cachedPathData, "_virtualPath", virtualPathObject);
ExpressionEvaluator.SetValue(cachedPathData, "_physicalPath", appPath);
#endif
ctx.Request.Browser = browser;
string filePath = ctx.Request.FilePath;
_wr = wr;
}

View File

@@ -1,5 +1,8 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using Spring.Collections;
using Spring.Util;
namespace Spring.TestSupport
@@ -8,7 +11,7 @@ namespace Spring.TestSupport
/// Test environment implementation.
/// </summary>
/// <author>Erich Eichinger</author>
internal class VirtualEnvironmentMock : IVirtualEnvironment, IDisposable
public class VirtualEnvironmentMock : IVirtualEnvironment, IDisposable
{
private readonly IVirtualEnvironment _prevEnvironment;
@@ -16,6 +19,8 @@ namespace Spring.TestSupport
private readonly string _pathInfo;
private string _currentExecutionFilePath;
private readonly string _applicationVirtualPath;
private ISessionState _session = new SessionMock();
private IDictionary _requestVariables = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
public VirtualEnvironmentMock(string currentVirtualFilePath, string pathInfo, string applicationVirtualPath, bool autoInitialize)
{
@@ -63,6 +68,18 @@ namespace Spring.TestSupport
return resultPath;
}
public ISessionState Session
{
get { return _session; }
set { _session = value; }
}
public IDictionary RequestVariables
{
get { return _requestVariables; }
set { _requestVariables = value; }
}
public void Dispose()
{
VirtualEnvironment.SetInstance(_prevEnvironment);

View File

@@ -21,11 +21,15 @@
#region Imports
using System;
using System.Collections.Specialized;
using System.Data;
using System.Web.UI.WebControls;
using Common.Logging;
using Common.Logging.Simple;
using NUnit.Framework;
using Spring.Context;
using Spring.Context.Support;
using Spring.Objects.Factory.Support;
using Spring.TestSupport;
#if NET_2_0
@@ -86,20 +90,36 @@ namespace Spring.Util
[Test, Explicit]
public void RunTestWithDI()
{
// LogManager.Adapter = new Common.Logging.Simple.TraceLoggerFactoryAdapter();
DataView dv = CreateDataSource();
IApplicationContext ctx = new StaticApplicationContext();
int runs = 1000;
StopWatch watch = new StopWatch();
using (watch.Start("Duration: {0}"))
using (TestWebContext wctx = new TestWebContext("/testpath", "testpage.aspx"))
{
for (int i = 0; i < runs; i++)
IApplicationContext ctx = new WebApplicationContext();
int runs = 1000;
StopWatch watch = new StopWatch();
using (watch.Start("Duration: {0}"))
{
DataGrid grid = new DataGrid();
Spring.Web.Support.WebDependencyInjectionUtils.InjectDependenciesRecursive(ctx, grid);
grid.DataSource = dv;
grid.DataBind();
for (int i = 0; i < runs; i++)
{
DataGrid grid = new DataGrid();
Spring.Web.Support.WebDependencyInjectionUtils.InjectDependenciesRecursive(ctx, grid);
grid.DataSource = dv;
grid.DataBind();
}
}
using (watch.Start("Duration: {0}"))
{
for (int i = 0; i < runs; i++)
{
DataGrid grid = new DataGrid();
grid.DataSource = dv;
grid.DataBind();
Spring.Web.Support.WebDependencyInjectionUtils.InjectDependenciesRecursive(ctx, grid);
}
}
}
}
@@ -112,7 +132,7 @@ namespace Spring.Util
Hashtable ht = new Hashtable();
Dictionary<object, object> dict = new Dictionary<object, object>();
for(int i = 0; i < 100000; i++)
for (int i = 0; i < 100000; i++)
{
ht.Add(i, new object());
dict.Add(new object(), new object());