Merge branch 'master' of git://github.com/SpringSource/spring-net.git into ivariablesourcedocs

This commit is contained in:
Marijn van der Zee
2011-12-19 16:18:54 +01:00
12 changed files with 2433 additions and 946 deletions

View File

@@ -525,8 +525,8 @@ namespace Spring.Context.Support
InvokeObjectFactoryPostProcessors(registryPostProcessorObjects, objectFactory);
InvokeObjectFactoryPostProcessors(regularPostProcessors, objectFactory);
// processedObjects.Add(objectMap.Keys);
// processedObjects.Add(objectMap.Keys);
foreach (DictionaryEntry entry in objectMap)
{
processedObjects.Add(entry.Key);
@@ -1240,6 +1240,34 @@ namespace Spring.Context.Support
return ObjectFactory.GetObjectNamesForType(type);
}
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
/// </summary>
/// <remarks>
/// <p>
/// Does consider objects created by <see cref="Spring.Objects.Factory.IFactoryObject"/>s,
/// or rather it considers the type of objects created by
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> (which means that
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s will be instantiated).
/// </p>
/// <p>
/// Does not consider any hierarchy this factory may participate in.
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match, or <see langword="null"/>
/// for all object names.
/// </typeparam>
/// <returns>
/// The names of all objects defined in this factory, or an empty array if none
/// are defined.
/// </returns>
public string[] GetObjectNamesForType<T>()
{
return GetObjectNamesForType(typeof(T));
}
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
@@ -1267,6 +1295,46 @@ namespace Spring.Context.Support
return ObjectFactory.GetObjectNamesForType(type, includePrototypes, includeFactoryObjects);
}
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
/// </summary>
/// <remarks>
/// <p>
/// Does consider objects created by <see cref="Spring.Objects.Factory.IFactoryObject"/>s,
/// or rather it considers the type of objects created by
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> (which means that
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s will be instantiated).
/// </p>
/// <p>
/// Does not consider any hierarchy this factory may participate in.
/// Use <see cref="ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(Spring.Objects.Factory.IListableObjectFactory,System.Type,bool,bool)"/>
/// to include beans in ancestor factories too.
/// &lt;p&gt;Note: Does &lt;i&gt;not&lt;/i&gt; ignore singleton objects that have been registered
/// by other means than bean definitions.
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match, or <see langword="null"/>
/// for all object names.
/// </typeparam>
/// <param name="includePrototypes">
/// Whether to include prototype objects too or just singletons (also applies to
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s).
/// </param>
/// <param name="includeFactoryObjects">
/// Whether to include <see cref="Spring.Objects.Factory.IFactoryObject"/>s too
/// or just normal objects.
/// </param>
/// <returns>
/// The names of all objects defined in this factory, or an empty array if none
/// are defined.
/// </returns>
public string[] GetObjectNamesForType<T>(bool includePrototypes, bool includeFactoryObjects)
{
return GetObjectNamesForType(typeof(T), includePrototypes, includeFactoryObjects);
}
/// <summary>
/// Return the names of all objects defined in this factory.
/// </summary>
@@ -1350,6 +1418,38 @@ namespace Spring.Context.Support
return GetObjectsOfType(type, true, true);
}
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
/// definitions or the value of
/// <see cref="Spring.Objects.Factory.IFactoryObject.ObjectType"/> in the case of
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
/// </summary>
/// <remarks>
/// <p>
/// This version of the <see cref="IListableObjectFactory.GetObjectsOfType(Type,bool,bool)"/>
/// method matches all kinds of object definitions, be they singletons, prototypes, or
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s. Typically, the results
/// of this method call will be the same as a call to
/// <code>IListableObjectFactory.GetObjectsOfType(type,true,true)</code> .
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match.
/// </typeparam>
/// <returns>
/// A <see cref="System.Collections.IDictionary"/> of the matching objects,
/// containing the object names as keys and the corresponding object instances
/// as values.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the objects could not be created.
/// </exception>
public IDictionary GetObjectsOfType<T>()
{
return GetObjectsOfType(typeof(T));
}
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
@@ -1383,6 +1483,82 @@ namespace Spring.Context.Support
return ObjectFactory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects);
}
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
/// definitions or the value of
/// <see cref="Spring.Objects.Factory.IFactoryObject.ObjectType"/> in the case of
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
/// </summary>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match.
/// </typeparam>
/// <param name="includePrototypes">
/// Whether to include prototype objects too or just singletons (also applies to
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s).
/// </param>
/// <param name="includeFactoryObjects">
/// Whether to include <see cref="Spring.Objects.Factory.IFactoryObject"/>s too
/// or just normal objects.
/// </param>
/// <returns>
/// A <see cref="System.Collections.IDictionary"/> of the matching objects,
/// containing the object names as keys and the corresponding object instances
/// as values.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the objects could not be created.
/// </exception>
public IDictionary GetObjectsOfType<T>(bool includePrototypes, bool includeFactoryObjects)
{
return GetObjectsOfType(typeof(T), includePrototypes, includeFactoryObjects);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <typeparam name="T">The type of the object to return.</typeparam>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectDefinitionStoreException">
/// If there is more than a single object of the requested type defined in the factory.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
public T GetObject<T>()
{
string[] objectNamesForType = GetObjectNamesForType(typeof(T));
if ((objectNamesForType == null) || (objectNamesForType.Length == 0))
{
throw new NoSuchObjectDefinitionException(typeof(T).FullName, "Requested Type not Defined in the Context.");
}
if (objectNamesForType.Length > 1)
{
throw new ObjectDefinitionStoreException(string.Format("More than one definition for {0} found in the Context.", typeof(T).FullName));
}
return (T)GetObject(objectNamesForType[0]);
}
/// <summary>
/// Return the number of objects defined in the factory.
/// </summary>
@@ -1457,6 +1633,27 @@ namespace Spring.Context.Support
}
/// <summary>
/// Determines whether the object with the given name matches the specified type.
/// </summary>
/// <remarks>More specifically, check whether a GetObject call for the given name
/// would return an object that is assignable to the specified target type.
/// Translates aliases back to the corresponding canonical bean name.
/// Will ask the parent factory if the bean cannot be found in this factory instance.
/// </remarks>
/// <param name="name">The name of the object to query.</param>
/// <typeparam name="T">Type of the target to match against.</typeparam>
/// <returns>
/// <c>true</c> if the object type matches; otherwise, <c>false</c>
/// if it doesn't match or cannot be determined yet.
/// </returns>
/// <exception cref="NoSuchObjectDefinitionException">Ff there is no object with the given name
/// </exception>
public bool IsTypeMatch<T>(string name)
{
return IsTypeMatch(name, typeof(T));
}
/// <summary>
/// Return an unconfigured(!) instance (possibly shared or independent) of the given object name.
/// </summary>
@@ -1495,6 +1692,44 @@ namespace Spring.Context.Support
return ObjectFactory.CreateObject(name, requiredType, arguments);
}
/// <summary>
/// Return an unconfigured(!) instance (possibly shared or independent) of the given object name.
/// </summary>
/// <param name="name">The name of the object to return.</param>
/// <typeparam name="T">
/// The <see cref="System.Type"/> the object may match. Can be an interface or
/// superclass of the actual class. For example, if the value is the
/// <see cref="System.Object"/> class, this method will succeed whatever the
/// class of the returned instance.
/// </typeparam>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a <see lang="static"/> factory method. If there is no factory method and the
/// supplied <paramref name="arguments"/> array is not <see lang="null"/>, then
/// match the argument values by type and call the object's constructor.
/// </param>
/// <returns>The unconfigured(!) instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type, object[])"/>
/// <remarks>
/// This method will only <b>instantiate</b> the requested object. It does <b>NOT</b> inject any dependencies!
/// </remarks>
public T CreateObject<T>(string name, object[] arguments)
{
return (T)CreateObject(name, typeof(T), arguments);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
@@ -1538,6 +1773,41 @@ namespace Spring.Context.Support
return ObjectFactory.GetObject(name);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <typeparam name="T">The type of the object to return.</typeparam>
/// <param name="name">The name of the object to return.</param>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
public T GetObject<T>(string name)
{
return (T)GetObject(name, typeof(T));
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
@@ -1578,6 +1848,49 @@ namespace Spring.Context.Support
return ObjectFactory.GetObject(name, arguments);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <param name="name">The name of the object to return.</param>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a static factory method. If there is no factory method and the
/// arguments are not null, then match the argument values by type and
/// call the object's constructor.
/// </param>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
public T GetObject<T>(string name, object[] arguments)
{
return (T)GetObject(name, typeof(T), arguments);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>

View File

@@ -120,6 +120,33 @@ namespace Spring.Objects.Factory
/// </returns>
string[] GetObjectNamesForType(Type type);
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
/// </summary>
/// <remarks>
/// <p>
/// Does consider objects created by <see cref="Spring.Objects.Factory.IFactoryObject"/>s,
/// or rather it considers the type of objects created by
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> (which means that
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s will be instantiated).
/// </p>
/// <p>
/// Does not consider any hierarchy this factory may participate in.
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match, or <see langword="null"/>
/// for all object names.
/// </typeparam>
/// <returns>
/// The names of all objects defined in this factory, or an empty array if none
/// are defined.
/// </returns>
string[] GetObjectNamesForType<T>();
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
@@ -157,6 +184,43 @@ namespace Spring.Objects.Factory
/// </returns>
string[] GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects);
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
/// </summary>
/// <remarks>
/// <p>
/// Does consider objects created by <see cref="Spring.Objects.Factory.IFactoryObject"/>s,
/// or rather it considers the type of objects created by
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> (which means that
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s will be instantiated).
/// </p>
/// <p>
/// Does not consider any hierarchy this factory may participate in.
/// Use <see cref="ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(Spring.Objects.Factory.IListableObjectFactory,System.Type,bool,bool)"/>
/// to include beans in ancestor factories too.
/// &lt;p&gt;Note: Does &lt;i&gt;not&lt;/i&gt; ignore singleton objects that have been registered
/// by other means than bean definitions.
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match, or <see langword="null"/>
/// for all object names.
/// </typeparam>
/// <param name="includePrototypes">
/// Whether to include prototype objects too or just singletons (also applies to
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s).
/// </param>
/// <param name="includeFactoryObjects">
/// Whether to include <see cref="Spring.Objects.Factory.IFactoryObject"/>s too
/// or just normal objects.
/// </param>
/// <returns>
/// The names of all objects defined in this factory, or an empty array if none
/// are defined.
/// </returns>
string[] GetObjectNamesForType<T>(bool includePrototypes, bool includeFactoryObjects);
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
@@ -185,6 +249,35 @@ namespace Spring.Objects.Factory
/// If the objects could not be created.
/// </exception>
IDictionary GetObjectsOfType(Type type);
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
/// definitions or the value of
/// <see cref="Spring.Objects.Factory.IFactoryObject.ObjectType"/> in the case of
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
/// </summary>
/// <remarks>
/// <p>
/// This version of the <see cref="IListableObjectFactory.GetObjectsOfType(Type,bool,bool)"/>
/// method matches all kinds of object definitions, be they singletons, prototypes, or
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s. Typically, the results
/// of this method call will be the same as a call to
/// <code>IListableObjectFactory.GetObjectsOfType(type,true,true)</code> .
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match.
/// </typeparam>
/// <returns>
/// A <see cref="System.Collections.IDictionary"/> of the matching objects,
/// containing the object names as keys and the corresponding object instances
/// as values.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the objects could not be created.
/// </exception>
IDictionary GetObjectsOfType<T>();
/// <summary>
/// Return the object instances that match the given object
@@ -212,9 +305,65 @@ namespace Spring.Objects.Factory
/// <exception cref="Spring.Objects.ObjectsException">
/// If the objects could not be created.
/// </exception>
IDictionary GetObjectsOfType(
Type type, bool includePrototypes, bool includeFactoryObjects);
IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects);
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
/// definitions or the value of
/// <see cref="Spring.Objects.Factory.IFactoryObject.ObjectType"/> in the case of
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
/// </summary>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match.
/// </typeparam>
/// <param name="includePrototypes">
/// Whether to include prototype objects too or just singletons (also applies to
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s).
/// </param>
/// <param name="includeFactoryObjects">
/// Whether to include <see cref="Spring.Objects.Factory.IFactoryObject"/>s too
/// or just normal objects.
/// </param>
/// <returns>
/// A <see cref="System.Collections.IDictionary"/> of the matching objects,
/// containing the object names as keys and the corresponding object instances
/// as values.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the objects could not be created.
/// </exception>
IDictionary GetObjectsOfType<T>(bool includePrototypes, bool includeFactoryObjects);
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <typeparam name="T">The type of the object to return.</typeparam>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectDefinitionStoreException">
/// If there is more than a single object of the requested type defined in the factory.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
T GetObject<T>();
}
}

View File

@@ -286,7 +286,39 @@ namespace Spring.Objects.Factory
/// If the object could not be created.
/// </exception>
object GetObject(string name);
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <typeparam name="T">The type of the object to return.</typeparam>
/// <param name="name">The name of the object to return.</param>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
T GetObject<T>(string name);
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
@@ -323,6 +355,46 @@ namespace Spring.Objects.Factory
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
object GetObject(string name, object[] arguments);
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <param name="name">The name of the object to return.</param>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a static factory method. If there is no factory method and the
/// arguments are not null, then match the argument values by type and
/// call the object's constructor.
/// </param>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
T GetObject<T>(string name, object[] arguments);
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
@@ -434,6 +506,24 @@ namespace Spring.Objects.Factory
/// </exception>
bool IsTypeMatch(string name, Type targetType);
/// <summary>
/// Determines whether the object with the given name matches the specified type.
/// </summary>
/// <remarks>More specifically, check whether a GetObject call for the given name
/// would return an object that is assignable to the specified target type.
/// Translates aliases back to the corresponding canonical bean name.
/// Will ask the parent factory if the bean cannot be found in this factory instance.
/// </remarks>
/// <param name="name">The name of the object to query.</param>
/// <typeparam name="T">Type of the target to match against.</typeparam>
/// <returns>
/// <c>true</c> if the object type matches; otherwise, <c>false</c>
/// if it doesn't match or cannot be determined yet.
/// </returns>
/// <exception cref="NoSuchObjectDefinitionException">Ff there is no object with the given name
/// </exception>
bool IsTypeMatch<T>(string name);
/// <summary>
/// Return an unconfigured(!) instance (possibly shared or independent) of the given object name.
/// </summary>
@@ -469,6 +559,41 @@ namespace Spring.Objects.Factory
/// </remarks>
object CreateObject(string name, Type requiredType, object[] arguments);
/// <summary>
/// Return an unconfigured(!) instance (possibly shared or independent) of the given object name.
/// </summary>
/// <param name="name">The name of the object to return.</param>
/// <typeparam name="T">
/// The <see cref="System.Type"/> the object may match. Can be an interface or
/// superclass of the actual class. For example, if the value is the
/// <see cref="System.Object"/> class, this method will succeed whatever the
/// class of the returned instance.
/// </typeparam>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a <see lang="static"/> factory method. If there is no factory method and the
/// supplied <paramref name="arguments"/> array is not <see lang="null"/>, then
/// match the argument values by type and call the object's constructor.
/// </param>
/// <returns>The unconfigured(!) instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type, object[])"/>
/// <remarks>
/// This method will only <b>instantiate</b> the requested object. It does <b>NOT</b> inject any dependencies!
/// </remarks>
T CreateObject<T>(string name, object[] arguments);
/// <summary>
/// Injects dependencies into the supplied <paramref name="target"/> instance
/// using the named object definition.

View File

@@ -266,6 +266,48 @@ namespace Spring.Objects.Factory.Support
#region Methods
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <param name="name">The name of the object to return.</param>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a static factory method. If there is no factory method and the
/// arguments are not null, then match the argument values by type and
/// call the object's constructor.
/// </param>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
public T GetObject<T>(string name, object[] arguments)
{
return (T)GetObject(name, typeof(T), arguments);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
@@ -1266,6 +1308,27 @@ namespace Spring.Objects.Factory.Support
}
}
/// <summary>
/// Determines whether the object with the given name matches the specified type.
/// </summary>
/// <remarks>More specifically, check whether a GetObject call for the given name
/// would return an object that is assignable to the specified target type.
/// Translates aliases back to the corresponding canonical bean name.
/// Will ask the parent factory if the bean cannot be found in this factory instance.
/// </remarks>
/// <param name="name">The name of the object to query.</param>
/// <typeparam name="T">Type of the target to match against.</typeparam>
/// <returns>
/// <c>true</c> if the object type matches; otherwise, <c>false</c>
/// if it doesn't match or cannot be determined yet.
/// </returns>
/// <exception cref="NoSuchObjectDefinitionException">Ff there is no object with the given name
/// </exception>
public bool IsTypeMatch<T>(string name)
{
return IsTypeMatch(name, typeof (T));
}
/// <summary>
/// Determines the <see cref="System.Type"/> of the object with the
/// supplied <paramref name="name"/>.
@@ -1801,6 +1864,44 @@ namespace Spring.Objects.Factory.Support
return GetObjectInternal(name, requiredType, arguments, true);
}
/// <summary>
/// Return an unconfigured(!) instance (possibly shared or independent) of the given object name.
/// </summary>
/// <param name="name">The name of the object to return.</param>
/// <typeparam name="T">
/// The <see cref="System.Type"/> the object may match. Can be an interface or
/// superclass of the actual class. For example, if the value is the
/// <see cref="System.Object"/> class, this method will succeed whatever the
/// class of the returned instance.
/// </typeparam>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a <see lang="static"/> factory method. If there is no factory method and the
/// supplied <paramref name="arguments"/> array is not <see lang="null"/>, then
/// match the argument values by type and call the object's constructor.
/// </param>
/// <returns>The unconfigured(!) instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type, object[])"/>
/// <remarks>
/// This method will only <b>instantiate</b> the requested object. It does <b>NOT</b> inject any dependencies!
/// </remarks>
public T CreateObject<T>(string name, object[] arguments)
{
return (T)CreateObject(name, typeof(T), arguments);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
@@ -1810,6 +1911,41 @@ namespace Spring.Objects.Factory.Support
return GetObjectInternal(name, null, null, false);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <typeparam name="T">The type of the object to return.</typeparam>
/// <param name="name">The name of the object to return.</param>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
public T GetObject<T>(string name)
{
return (T)GetObject(name);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>

View File

@@ -662,6 +662,34 @@ namespace Spring.Objects.Factory.Support
return GetObjectNamesForType(type, true, true);
}
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
/// </summary>
/// <remarks>
/// <p>
/// Does consider objects created by <see cref="Spring.Objects.Factory.IFactoryObject"/>s,
/// or rather it considers the type of objects created by
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> (which means that
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s will be instantiated).
/// </p>
/// <p>
/// Does not consider any hierarchy this factory may participate in.
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match, or <see langword="null"/>
/// for all object names.
/// </typeparam>
/// <returns>
/// The names of all objects defined in this factory, or an empty array if none
/// are defined.
/// </returns>
public string[] GetObjectNamesForType<T>()
{
return GetObjectNamesForType(typeof (T));
}
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
@@ -690,6 +718,46 @@ namespace Spring.Objects.Factory.Support
return (string[])ArrayList.Adapter(objectNames).ToArray(typeof(string));
}
/// <summary>
/// Return the names of objects matching the given <see cref="System.Type"/>
/// (including subclasses), judging from the object definitions.
/// </summary>
/// <remarks>
/// <p>
/// Does consider objects created by <see cref="Spring.Objects.Factory.IFactoryObject"/>s,
/// or rather it considers the type of objects created by
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> (which means that
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s will be instantiated).
/// </p>
/// <p>
/// Does not consider any hierarchy this factory may participate in.
/// Use <see cref="ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(Spring.Objects.Factory.IListableObjectFactory,System.Type,bool,bool)"/>
/// to include beans in ancestor factories too.
/// &lt;p&gt;Note: Does &lt;i&gt;not&lt;/i&gt; ignore singleton objects that have been registered
/// by other means than bean definitions.
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match, or <see langword="null"/>
/// for all object names.
/// </typeparam>
/// <param name="includePrototypes">
/// Whether to include prototype objects too or just singletons (also applies to
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s).
/// </param>
/// <param name="includeFactoryObjects">
/// Whether to include <see cref="Spring.Objects.Factory.IFactoryObject"/>s too
/// or just normal objects.
/// </param>
/// <returns>
/// The names of all objects defined in this factory, or an empty array if none
/// are defined.
/// </returns>
public string[] GetObjectNamesForType<T>(bool includePrototypes, bool includeFactoryObjects)
{
return GetObjectNamesForType(typeof (T), includePrototypes, includeFactoryObjects);
}
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
@@ -714,6 +782,38 @@ namespace Spring.Objects.Factory.Support
return GetObjectsOfType(type, true, true);
}
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
/// definitions or the value of
/// <see cref="Spring.Objects.Factory.IFactoryObject.ObjectType"/> in the case of
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
/// </summary>
/// <remarks>
/// <p>
/// This version of the <see cref="IListableObjectFactory.GetObjectsOfType(Type,bool,bool)"/>
/// method matches all kinds of object definitions, be they singletons, prototypes, or
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s. Typically, the results
/// of this method call will be the same as a call to
/// <code>IListableObjectFactory.GetObjectsOfType(type,true,true)</code> .
/// </p>
/// </remarks>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match.
/// </typeparam>
/// <returns>
/// A <see cref="System.Collections.IDictionary"/> of the matching objects,
/// containing the object names as keys and the corresponding object instances
/// as values.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the objects could not be created.
/// </exception>
public IDictionary GetObjectsOfType<T>()
{
return GetObjectsOfType(typeof (T));
}
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses).
@@ -774,6 +874,82 @@ namespace Spring.Objects.Factory.Support
return result;
}
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses), judging from either object
/// definitions or the value of
/// <see cref="Spring.Objects.Factory.IFactoryObject.ObjectType"/> in the case of
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
/// </summary>
/// <typeparam name="T">
/// The <see cref="System.Type"/> (class or interface) to match.
/// </typeparam>
/// <param name="includePrototypes">
/// Whether to include prototype objects too or just singletons (also applies to
/// <see cref="Spring.Objects.Factory.IFactoryObject"/>s).
/// </param>
/// <param name="includeFactoryObjects">
/// Whether to include <see cref="Spring.Objects.Factory.IFactoryObject"/>s too
/// or just normal objects.
/// </param>
/// <returns>
/// A <see cref="System.Collections.IDictionary"/> of the matching objects,
/// containing the object names as keys and the corresponding object instances
/// as values.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the objects could not be created.
/// </exception>
public IDictionary GetObjectsOfType<T>(bool includePrototypes, bool includeFactoryObjects)
{
return GetObjectsOfType(typeof (T), includePrototypes, includeFactoryObjects);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <remarks>
/// <para>
/// This method allows an object factory to be used as a replacement for the
/// Singleton or Prototype design pattern.
/// </para>
/// <para>
/// Note that callers should retain references to returned objects. There is no
/// guarantee that this method will be implemented to be efficient. For example,
/// it may be synchronized, or may need to run an RDBMS query.
/// </para>
/// <para>
/// Will ask the parent factory if the object cannot be found in this factory
/// instance.
/// </para>
/// </remarks>
/// <typeparam name="T">The type of the object to return.</typeparam>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectDefinitionStoreException">
/// If there is more than a single object of the requested type defined in the factory.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
public T GetObject<T>()
{
string[] objectNamesForType = GetObjectNamesForType(typeof(T));
if ((objectNamesForType == null) || (objectNamesForType.Length == 0))
{
throw new NoSuchObjectDefinitionException(typeof(T).FullName, "Requested Type not Defined in the Context.");
}
if (objectNamesForType.Length > 1)
{
throw new ObjectDefinitionStoreException(string.Format("More than one definition for {0} found in the Context.", typeof(T).FullName));
}
return (T)GetObject(objectNamesForType[0]);
}
/// <summary>
/// Return the object instances that match the given object
/// <see cref="System.Type"/> (including subclasses).

View File

@@ -125,16 +125,80 @@ namespace Spring.Util
/// <returns>The target method.</returns>
/// <seealso cref="MapInterfaceMethodToImplementationIfNecessary"/>
public static MethodInfo GetMethod(
Type targetType, string method, Type[] argumentTypes)
Type targetType, string method, Type[] argumentTypes)
{
return GetMethod(targetType, method, argumentTypes, 0);
}
/// <summary>
/// Returns method for the specified <see cref="System.Type"/>, method
/// name and argument
/// <see cref="System.Type"/>s.
/// </summary>
/// <remarks>
/// <para>Searches with BindingFlags</para>
/// <para>When dealing with interface methods, you probable want to 'normalize' method references by calling
/// <see cref="MapInterfaceMethodToImplementationIfNecessary"/>.
/// </para>
/// </remarks>
/// <param name="targetType">
/// The target <see cref="System.Type"/> to find the method on.
/// </param>
/// <param name="method">The method to find.</param>
/// <param name="argumentTypes">
/// The argument <see cref="System.Type"/>s. May be
/// <see langword="null"/> if the method has no arguments.
/// </param>
/// <param name="genericArgumentsCount">Number of Generic Arguments in the method</param>
/// <returns>The target method.</returns>
/// <seealso cref="MapInterfaceMethodToImplementationIfNecessary"/>
public static MethodInfo GetMethod(
Type targetType, string method, Type[] argumentTypes, int genericArgumentsCount)
{
AssertUtils.ArgumentNotNull(targetType, "Type must not be null");
// try method exactly as specified first...
MethodInfo retMethod = targetType.GetMethod(
method,
ReflectionUtils.AllMembersCaseInsensitiveFlags,
null,
argumentTypes == null ? Type.EmptyTypes : argumentTypes,
null);
MethodInfo retMethod = null;
MethodInfo[] methods = targetType.GetMethods(ReflectionUtils.AllMembersCaseInsensitiveFlags);
foreach (MethodInfo candidate in methods)
{
if (candidate.Name.ToLower() == method.ToLower())
{
Type[] parameterTypes = Array.ConvertAll<ParameterInfo, Type>(candidate.GetParameters(), delegate(ParameterInfo i) { return i.ParameterType; });
bool typesMatch = false;
bool zeroTypeArguments = argumentTypes.Length == 0;
if (parameterTypes.Length == argumentTypes.Length && !zeroTypeArguments)
{
for (int i = 0; i < parameterTypes.Length; i++)
{
typesMatch = parameterTypes[i] == argumentTypes[i];
if (!typesMatch)
{
break;
}
}
}
if (typesMatch || zeroTypeArguments)
{
if (candidate.GetGenericArguments().Length == genericArgumentsCount)
{
retMethod = candidate;
break;
}
}
}
}
/*return (from method in type.GetMethods()
where method.Name == name
where parameterTypes.SequenceEqual(method.GetParameters().Select(p => p.ParameterType))
where method.GetGenericArguments().Count() == genericArguments
select method).Single();*/
if (retMethod == null)
{
@@ -248,6 +312,79 @@ namespace Spring.Util
}
return names;
}
public static MethodInfo GetGenericMethod(Type type, string methodName, Type[] typeArguments, Type[] parameterTypes)
{
MethodInfo methodInfo = null;
if (typeArguments == null)
{
// Non-Generic Method
methodInfo = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, parameterTypes, null);
}
else
{
// Generic Method
MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
// Loop thru all Methods
foreach (MethodInfo method in methods)
{
if (method.Name != methodName)
{
// Name does not match
continue;
}
if (!method.IsGenericMethod)
{
// Non-Generic
continue;
}
// Compare the Method Parameters
bool paramsOk = false;
if (method.GetParameters().Length == parameterTypes.Length)
{
// Count Matches
paramsOk = true;
// Check each Type
for (int i = 0; i < method.GetParameters().Length; i++)
{
if (method.GetParameters()[i].ParameterType != parameterTypes[i])
{
// Parameter Type doesn't Match
paramsOk = false;
break;
}
}
}
if (!paramsOk)
{
// Parameters didn't match
continue;
}
// Check the Generic Arguments
bool argsOk = false;
if (method.GetGenericArguments().Length == typeArguments.Length)
{
// Count Matches
argsOk = true;
// TODO: Check for "where" Limitation in the Generic Definition
}
if (!argsOk)
{
// Generic Arguments didn't match
continue;
}
// If we're here, we got the right Method
methodInfo = method.MakeGenericMethod(typeArguments);
break;
}
}
return methodInfo;
}
#endif
/// <summary>

View File

@@ -28,6 +28,7 @@ using System.Reflection.Emit;
using Spring.Objects.Factory;
using Spring.Proxy;
using Spring.Util;
#endregion
@@ -42,7 +43,8 @@ namespace Spring.ServiceModel.Support
#region Fields
private static readonly MethodInfo GetObject =
typeof(IObjectFactory).GetMethod("GetObject", new Type[] { typeof(string) });
//typeof(IObjectFactory).GetMethod("GetObject", new Type[] { typeof(string) });
ReflectionUtils.GetMethod(typeof (IObjectFactory), "GetObject", new Type[] {typeof (string)});
private IObjectFactory objectFactory;
private static Hashtable s_serviceTypeCache = new Hashtable();

View File

@@ -23,32 +23,32 @@
using System;
using Common.Logging;
using Common.Logging.Simple;
using DotNetMock.Dynamic;
using NUnit.Framework;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Xml;
using Rhino.Mocks;
#endregion
namespace Spring.Aop.Target
{
/// <summary>
/// Unit tests for the PrototypeTargetSource class.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Federico Spinazzi</author>
[TestFixture]
public sealed class PrototypeTargetSourceTests
{
/// <summary>
/// The setup logic executed before the execution of this test fixture.
/// </summary>
[TestFixtureSetUp]
public void FixtureSetUp()
{
// enable (null appender) logging, just to ensure that the logging code is correct
LogManager.Adapter = new NoOpLoggerFactoryAdapter();
}
/// <summary>
/// Unit tests for the PrototypeTargetSource class.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Federico Spinazzi</author>
[TestFixture]
public sealed class PrototypeTargetSourceTests
{
/// <summary>
/// The setup logic executed before the execution of this test fixture.
/// </summary>
[TestFixtureSetUp]
public void FixtureSetUp()
{
// enable (null appender) logging, just to ensure that the logging code is correct
LogManager.Adapter = new NoOpLoggerFactoryAdapter();
}
/// <summary>
/// Test that multiple invocations of the prototype object will result
@@ -60,83 +60,106 @@ namespace Spring.Aop.Target
{
int initialCount = 10;
IObjectFactory of = new XmlObjectFactory(new ReadOnlyXmlTestResource("prototypeTargetSourceTests.xml", GetType()));
ISideEffectObject singleton = (ISideEffectObject) of.GetObject("singleton");
ISideEffectObject singleton = (ISideEffectObject)of.GetObject("singleton");
Assert.AreEqual(initialCount, singleton.Count);
singleton.doWork();
Assert.AreEqual(initialCount + 1, singleton.Count);
ISideEffectObject prototype = (ISideEffectObject) of.GetObject("prototype");
ISideEffectObject prototype = (ISideEffectObject)of.GetObject("prototype");
Assert.AreEqual(initialCount, prototype.Count);
singleton.doWork();
Assert.AreEqual(initialCount, prototype.Count);
ISideEffectObject prototypeByName = (ISideEffectObject) of.GetObject("prototypeByName");
ISideEffectObject prototypeByName = (ISideEffectObject)of.GetObject("prototypeByName");
Assert.AreEqual(initialCount, prototypeByName.Count);
singleton.doWork();
Assert.AreEqual(initialCount, prototypeByName.Count);
}
[Test]
public void TargetType()
{
SideEffectObject target = new SideEffectObject();
IDynamicMock mock = new DynamicMock(typeof (IObjectFactory));
mock.ExpectAndReturn("IsPrototype", true, null);
mock.ExpectAndReturn("GetType", typeof(SideEffectObject), null);
PrototypeTargetSource source = new PrototypeTargetSource();
source.ObjectFactory = (IObjectFactory) mock.Object;
Assert.AreEqual(target.GetType(), source.TargetType, "Wrong TargetType being returned.");
mock.Verify();
}
[Test]
public void TargetType()
{
MockRepository mocks = new MockRepository();
SideEffectObject target = new SideEffectObject();
[Test]
public void IsStatic()
{
PrototypeTargetSource source = new PrototypeTargetSource();
Assert.IsFalse(source.IsStatic, "Must not be static.");
}
IObjectFactory factory = mocks.CreateMock<IObjectFactory>();
[Test]
public void WithNonSingletonTargetObject()
{
IDynamicMock mock = new DynamicMock(typeof (IObjectFactory));
const string objectName = "Foo";
mock.ExpectAndReturn("IsPrototype", false, objectName);
PrototypeTargetSource source = new PrototypeTargetSource();
source.TargetObjectName = objectName;
try
{
source.ObjectFactory = (IObjectFactory) mock.Object;
Assert.Fail("Should have thrown an ObjectDefinitionStoreException by this point.");
}
catch (ObjectDefinitionStoreException)
{
mock.Verify();
}
}
using (mocks.Record())
{
Expect.Call(factory.IsPrototype(null)).Return(true);
Expect.Call(factory.GetType(null)).Return(typeof(SideEffectObject));
}
[Test]
public void GetTarget()
{
SideEffectObject target = new SideEffectObject();
IDynamicMock mock = new DynamicMock(typeof (IObjectFactory));;
mock.ExpectAndReturn("IsPrototype", true, "foo");
mock.ExpectAndReturn("GetObject", target, "foo");
mock.ExpectAndReturn("GetType", typeof (string), "foo");
PrototypeTargetSource source = new PrototypeTargetSource();
source.TargetObjectName = "foo";
source.ObjectFactory = (IObjectFactory) mock.Object;
Assert.IsTrue(object.ReferenceEquals(source.GetTarget(), target),
"Initial target source reference not being returned by GetTarget().");
mock.Verify();
}
using (mocks.Playback())
{
PrototypeTargetSource source = new PrototypeTargetSource();
source.ObjectFactory = factory;
Assert.AreEqual(target.GetType(), source.TargetType, "Wrong TargetType being returned.");
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void AfterPropertiesSetWithoutTargetObjectNameBeingSet()
{
PrototypeTargetSource source = new PrototypeTargetSource();
source.AfterPropertiesSet();
}
}
}
[Test]
public void IsStatic()
{
PrototypeTargetSource source = new PrototypeTargetSource();
Assert.IsFalse(source.IsStatic, "Must not be static.");
}
[Test]
public void WithNonSingletonTargetObject()
{
MockRepository mocks = new MockRepository();
IObjectFactory factory = mocks.CreateMock<IObjectFactory>();
const string objectName = "Foo";
using (mocks.Record())
{
Expect.Call(factory.IsPrototype(objectName)).Return(false);
}
using (mocks.Playback())
{
PrototypeTargetSource source = new PrototypeTargetSource();
source.TargetObjectName = objectName;
Assert.Throws<ObjectDefinitionStoreException>(delegate { source.ObjectFactory = factory; });
}
}
[Test]
public void GetTarget()
{
MockRepository mocks = new MockRepository();
IObjectFactory factory = mocks.CreateMock<IObjectFactory>();
SideEffectObject target = new SideEffectObject();
using (mocks.Record())
{
Expect.Call(factory.IsPrototype("foo")).Return(true);
Expect.Call(factory.GetObject("foo")).Return(target);
Expect.Call(factory.GetType("foo")).Return(typeof(string));
}
using (mocks.Playback())
{
PrototypeTargetSource source = new PrototypeTargetSource();
source.TargetObjectName = "foo";
source.ObjectFactory = factory;
Assert.IsTrue(object.ReferenceEquals(source.GetTarget(), target),
"Initial target source reference not being returned by GetTarget().");
}
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void AfterPropertiesSetWithoutTargetObjectNameBeingSet()
{
PrototypeTargetSource source = new PrototypeTargetSource();
source.AfterPropertiesSet();
}
}
}

View File

@@ -25,7 +25,7 @@ using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using AopAlliance.Intercept;
using DotNetMock.Dynamic;
using Rhino.Mocks;
using NUnit.Framework;
using Spring.Caching;
using Spring.Context;
@@ -43,22 +43,24 @@ namespace Spring.Aspects.Cache
{
object[] IGNORED_ARGS = null;
private IDynamicMock mockInvocation;
private IDynamicMock mockContext;
private IMethodInvocation mockInvocation;
private IApplicationContext mockContext;
private CacheResultAdvice advice;
private ICache resultCache;
private ICache itemCache;
private ICache binaryFormatterCache;
private CacheResultTarget cacheResultTarget = new CacheResultTarget();
private MockRepository mocks;
[SetUp]
public void SetUp()
{
mockInvocation = new DynamicMock( typeof( IMethodInvocation ) );
mockContext = new DynamicMock( typeof( IApplicationContext ) );
mocks = new MockRepository();
mockInvocation = mocks.CreateMock<IMethodInvocation>();
mockContext = mocks.CreateMock<IApplicationContext>();
advice = new CacheResultAdvice();
advice.ApplicationContext = (IApplicationContext)mockContext.Object;
advice.ApplicationContext = mockContext;
resultCache = new NonExpiringCache();
itemCache = new NonExpiringCache();
@@ -72,339 +74,376 @@ namespace Spring.Aspects.Cache
[Test]
public void CacheResultOfMethodThatReturnsNull()
{
MethodInfo method = new VoidMethod( cacheResultTarget.ReturnsNothing ).Method;
MethodInfo method = new VoidMethod(cacheResultTarget.ReturnsNothing).Method;
object expectedReturnValue = null;
ExpectAttributeRetrieval( method );
ExpectCacheKeyGeneration( method, null );
ExpectCacheInstanceRetrieval( "results", resultCache );
ExpectCallToProceed( expectedReturnValue );
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, null);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(expectedReturnValue);
}
using (mocks.Playback())
{
// check that the null retVal is cached as well - it might be
// the result of an expensive webservice/database call etc.
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
}
// check that the null retVal is cached as well - it might be
// the result of an expensive webservice/database call etc.
object returnValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreEqual( expectedReturnValue, returnValue );
Assert.AreEqual( 1, resultCache.Count );
mockInvocation.Verify();
mockContext.Verify();
}
[Test]
public void CacheResultOfMethodThatReturnsNullWithSerializingCache()
{
MethodInfo method = new VoidMethod(cacheResultTarget.ReturnsNothing).Method;
object expectedReturnValue = null;
MethodInfo method = new VoidMethod(cacheResultTarget.ReturnsNothing).Method;
object expectedReturnValue = null;
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, null);
ExpectCacheInstanceRetrieval("results", binaryFormatterCache);
ExpectCallToProceed(expectedReturnValue);
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, null);
ExpectCacheInstanceRetrieval("results", binaryFormatterCache);
ExpectCallToProceed(expectedReturnValue);
}
// check that the null retVal is cached as well - it might be
// the result of an expensive webservice/database call etc.
object returnValue = advice.Invoke((IMethodInvocation) mockInvocation.Object);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, binaryFormatterCache.Count);
using (mocks.Playback())
{
// check that the null retVal is cached as well - it might be
// the result of an expensive webservice/database call etc.
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, binaryFormatterCache.Count);
// and again, but without Proceed()...
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, null);
ExpectCacheInstanceRetrieval("results", binaryFormatterCache);
// cached value should be returned
object cachedValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
Assert.IsNull(cachedValue, "Should recognize cached value as null-value marker.");
mockInvocation.Verify();
mockContext.Verify();
// cached value should be returned
object cachedValue = advice.Invoke(mockInvocation);
Assert.IsNull(cachedValue, "Should recognize cached value as null-value marker.");
}
}
[Test]
public void CacheResultOfMethodThatReturnsObject()
{
MethodInfo method = new IntMethod( cacheResultTarget.ReturnsScalar ).Method;
MethodInfo method = new IntMethod(cacheResultTarget.ReturnsScalar).Method;
object expectedReturnValue = CacheResultTarget.Scalar;
ExpectAttributeRetrieval( method );
ExpectCacheKeyGeneration( method, null );
ExpectCacheInstanceRetrieval( "results", resultCache );
ExpectCallToProceed( expectedReturnValue );
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, null);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(expectedReturnValue);
}
// return value should be added to cache
object returnValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreEqual( expectedReturnValue, returnValue );
Assert.AreEqual( 1, resultCache.Count );
using (mocks.Playback())
{
// return value should be added to cache
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
// and again, but without Proceed()...
ExpectAttributeRetrieval( method );
ExpectCacheKeyGeneration( method, null );
ExpectCacheInstanceRetrieval( "results", resultCache );
// cached value should be returned
object cachedValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreEqual( expectedReturnValue, cachedValue );
Assert.AreEqual( 1, resultCache.Count );
Assert.AreSame( returnValue, cachedValue );
mockInvocation.Verify();
mockContext.Verify();
// cached value should be returned
object cachedValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, cachedValue);
Assert.AreEqual(1, resultCache.Count);
Assert.AreSame(returnValue, cachedValue);
}
}
[Test]
public void CacheResultOfMethodThatReturnsCollection()
{
MethodInfo method = new EnumerableResultMethod( cacheResultTarget.ReturnsCollection ).Method;
object expectedReturnValue = new object[] {"one", "two", "three"};
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.ReturnsCollection).Method;
object expectedReturnValue = new object[] { "one", "two", "three" };
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(new object[] { "one", "two", "three" });
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(new object[] { "one", "two", "three" });
}
// return value should be added to cache
object returnValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
using (mocks.Playback())
{
// return value should be added to cache
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
// and again, but without Proceed()...
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
// cached value should be returned
object cachedValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
Assert.AreEqual(expectedReturnValue, cachedValue);
Assert.AreNotSame(expectedReturnValue, cachedValue);
Assert.AreEqual(expectedReturnValue, resultCache.Get(5));
Assert.AreEqual( 1, resultCache.Count );
Assert.AreSame( returnValue, cachedValue );
Assert.AreSame( cachedValue, resultCache.Get( 5 ) );
mockInvocation.Verify();
mockContext.Verify();
// cached value should be returned
object cachedValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, cachedValue);
Assert.AreNotSame(expectedReturnValue, cachedValue);
Assert.AreEqual(expectedReturnValue, resultCache.Get(5));
Assert.AreEqual(1, resultCache.Count);
Assert.AreSame(returnValue, cachedValue);
Assert.AreSame(cachedValue, resultCache.Get(5));
}
}
[Test]
public void CacheResultAndItemsOfMethodThatReturnsCollection()
{
MethodInfo method = new EnumerableResultMethod( cacheResultTarget.ReturnsCollectionAndItems ).Method;
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.ReturnsCollectionAndItems).Method;
object expectedReturnValue = new object[] { "one", "two", "three" };
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval("items", itemCache);
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval("items", itemCache);
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
}
// and again, but without Proceed() and item cache access...
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
using (mocks.Playback())
{
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
// cached value should be returned
object cachedValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
Assert.AreEqual(expectedReturnValue, cachedValue);
Assert.AreNotSame(expectedReturnValue, cachedValue);
Assert.AreEqual(expectedReturnValue, resultCache.Get(5));
Assert.AreEqual( 1, resultCache.Count );
Assert.AreEqual( 3, itemCache.Count );
Assert.AreSame( returnValue, cachedValue );
Assert.AreSame( cachedValue, resultCache.Get( 5 ) );
// cached value should be returned
object cachedValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, cachedValue);
Assert.AreNotSame(expectedReturnValue, cachedValue);
Assert.AreEqual(expectedReturnValue, resultCache.Get(5));
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
Assert.AreSame(returnValue, cachedValue);
Assert.AreSame(cachedValue, resultCache.Get(5));
mockInvocation.Verify();
mockContext.Verify();
}
}
[Test]
public void CacheOnlyItemsOfMethodThatReturnsCollection()
{
MethodInfo method = new EnumerableResultMethod( cacheResultTarget.ReturnsItems ).Method;
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.ReturnsItems).Method;
object expectedReturnValue = new object[] { "one", "two", "three" };
mocks.Record();
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval("items", itemCache);
mocks.ReplayAll();
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(0, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
// and again, but without Proceed() and item cache access...
mocks.Verify(mockInvocation);
mocks.BackToRecord(mockInvocation);
ExpectAttributeRetrieval(method);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval( "items", itemCache );
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
// new return value should be returned
object newReturnValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreEqual( expectedReturnValue, newReturnValue );
Assert.AreEqual( 0, resultCache.Count );
Assert.AreEqual( 3, itemCache.Count );
Assert.AreEqual( "two", itemCache.Get( "two" ) );
Assert.AreNotSame( returnValue, newReturnValue );
mocks.Replay(mockInvocation);
mockInvocation.Verify();
mockContext.Verify();
object newReturnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, newReturnValue);
Assert.AreEqual(0, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
Assert.AreEqual("two", itemCache.Get("two"));
Assert.AreNotSame(returnValue, newReturnValue);
mocks.VerifyAll();
}
[Test]
public void CacheOnlyItemsOfMethodThatReturnsCollectionWithinTwoDifferentCaches()
{
MethodInfo method = new EnumerableResultMethod( cacheResultTarget.MultipleCacheResultItems ).Method;
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.MultipleCacheResultItems).Method;
object expectedReturnValue = new object[] { "one", "two", "three" };
mocks.Record();
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval( "items", itemCache );
ExpectCacheInstanceRetrieval( "items", itemCache );
ExpectCacheInstanceRetrieval("items", itemCache);
mocks.ReplayAll();
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreEqual( expectedReturnValue, returnValue );
Assert.AreEqual( 0, resultCache.Count );
Assert.AreEqual( 6, itemCache.Count );
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(0, resultCache.Count);
Assert.AreEqual(6, itemCache.Count);
mocks.Verify(mockInvocation);
mocks.BackToRecord(mockInvocation);
// and again, but without Proceed() and item cache access...
ExpectAttributeRetrieval( method );
ExpectCallToProceed( new object[] { "one", "two", "three" } );
ExpectCacheInstanceRetrieval( "items", itemCache );
ExpectCacheInstanceRetrieval( "items", itemCache );
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
mocks.Replay(mockInvocation);
// new return value should be returned
object newReturnValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreEqual( expectedReturnValue, newReturnValue );
Assert.AreEqual( 0, resultCache.Count );
Assert.AreEqual( 6, itemCache.Count );
Assert.AreEqual( "two", itemCache.Get( "two" ) );
Assert.AreEqual( "two", itemCache.Get( "TWO" ) );
Assert.AreNotSame( returnValue, newReturnValue );
object newReturnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, newReturnValue);
Assert.AreEqual(0, resultCache.Count);
Assert.AreEqual(6, itemCache.Count);
Assert.AreEqual("two", itemCache.Get("two"));
Assert.AreEqual("two", itemCache.Get("TWO"));
Assert.AreNotSame(returnValue, newReturnValue);
mockInvocation.Verify();
mockContext.Verify();
mocks.VerifyAll();
}
[Test]
public void CacheOnlyItemsOfMethodThatReturnsCollectionOnCondition()
{
MethodInfo method = new EnumerableResultMethod( cacheResultTarget.CacheResultItemsWithCondition ).Method;
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.CacheResultItemsWithCondition).Method;
object expectedReturnValue = new object[] { "one", "two", "three" };
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval( "items", itemCache );
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval("items", itemCache);
}
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreEqual( expectedReturnValue, returnValue );
Assert.AreEqual( 2, itemCache.Count );
Assert.AreEqual( "two", itemCache.Get( "two" ) );
Assert.AreEqual( "three", itemCache.Get( "three" ) );
using (mocks.Playback())
{
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(2, itemCache.Count);
Assert.AreEqual("two", itemCache.Get("two"));
Assert.AreEqual("three", itemCache.Get("three"));
}
mockInvocation.Verify();
mockContext.Verify();
}
[Test]
public void CacheResultOfMethodThatReturnsCollectionOnCondition()
{
MethodInfo method = new EnumerableResultMethod( cacheResultTarget.CacheResultWithCondition ).Method;
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.CacheResultWithCondition).Method;
object expectedReturnValue = new object[] { };
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(new object[] { });
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(new object[] { });
}
// return value should not be added to cache
object returnValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreEqual( expectedReturnValue, returnValue );
Assert.AreEqual( 0, resultCache.Count );
mockInvocation.Verify();
mockContext.Verify();
using (mocks.Playback())
{
// return value should not be added to cache
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(0, resultCache.Count);
}
}
[Test]
public void AcceptsEnumerableOnlyReturn()
{
MethodInfo method = new EnumerableResultMethod( cacheResultTarget.ReturnsEnumerableOnlyAndItems ).Method;
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.ReturnsEnumerableOnlyAndItems).Method;
object[] args = new object[] { "one", "two", "three" };
EnumerableOnlyResult expectedReturnValue = new EnumerableOnlyResult(args);
mocks.Record();
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue.InnerArray);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(expectedReturnValue);
ExpectCacheInstanceRetrieval("items", itemCache);
mocks.ReplayAll();
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
Assert.AreSame(expectedReturnValue, returnValue);
Assert.AreSame(expectedReturnValue, resultCache.Get(5));
mocks.Verify(mockInvocation);
mocks.BackToRecord(mockInvocation);
// and again, but without Proceed() and item cache access...
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, IGNORED_ARGS);
ExpectCacheInstanceRetrieval("results", resultCache);
mocks.Replay(mockInvocation);
// cached value should be returned, cache remains unchanged
object cachedValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
object cachedValue = advice.Invoke(mockInvocation);
Assert.AreSame(expectedReturnValue, cachedValue);
Assert.AreSame(returnValue, cachedValue );
Assert.AreSame(returnValue, cachedValue);
Assert.AreSame(expectedReturnValue, resultCache.Get(5));
Assert.AreEqual( 1, resultCache.Count );
Assert.AreEqual( 3, itemCache.Count );
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
mockInvocation.Verify();
mockContext.Verify();
mocks.VerifyAll();
}
[Test]
public void CacheResultOfMethodThatReturnsCollectionContainingNullItems()
{
MethodInfo method = new EnumerableResultMethod( cacheResultTarget.ReturnsEnumerableOnlyAndItems ).Method;
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.ReturnsEnumerableOnlyAndItems).Method;
object expectedReturnValue = new object[] { null, "two", null };
ExpectAttributeRetrieval( method );
ExpectCacheKeyGeneration( method, 5, expectedReturnValue );
ExpectCacheInstanceRetrieval( "results", resultCache );
ExpectCallToProceed( expectedReturnValue );
ExpectCacheInstanceRetrieval( "items", itemCache );
mocks.Record();
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(expectedReturnValue);
ExpectCacheInstanceRetrieval("items", itemCache);
mocks.ReplayAll();
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
Assert.AreSame( expectedReturnValue, returnValue );
Assert.AreEqual( 1, resultCache.Count );
Assert.AreEqual( 2, itemCache.Count ); // 2 null items result into 1 cached item
object returnValue = advice.Invoke(mockInvocation);
Assert.AreSame(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(2, itemCache.Count); // 2 null items result into 1 cached item
mocks.Verify(mockInvocation);
mocks.BackToRecord(mockInvocation);
// and again, but without Proceed() and item cache access...
ExpectAttributeRetrieval( method );
ExpectCacheKeyGeneration( method, 5, IGNORED_ARGS );
ExpectCacheInstanceRetrieval( "results", resultCache );
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, IGNORED_ARGS);
mocks.Replay(mockInvocation);
// cached value should be returned
object cachedValue = advice.Invoke( (IMethodInvocation)mockInvocation.Object );
object cachedValue = advice.Invoke(mockInvocation);
Assert.AreSame(expectedReturnValue, cachedValue);
Assert.AreSame(returnValue, cachedValue );
Assert.AreSame(returnValue, cachedValue);
Assert.AreSame(expectedReturnValue, resultCache.Get(5));
Assert.AreEqual( 1, resultCache.Count );
Assert.AreEqual( 2, itemCache.Count );
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(2, itemCache.Count);
mockInvocation.Verify();
mockContext.Verify();
mocks.VerifyAll();
}
[Test]
@@ -413,19 +452,22 @@ namespace Spring.Aspects.Cache
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.CacheResultWithMethodInfo).Method;
object expectedReturnValue = new object[] { "one", "two", "three" };
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(new object[] { "one", "two", "three" });
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCacheInstanceRetrieval("results", resultCache);
ExpectCallToProceed(new object[] { "one", "two", "three" });
}
// return value should be added to cache
object returnValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(returnValue, resultCache.Get("CacheResultWithMethodInfo-5"));
mockInvocation.Verify();
mockContext.Verify();
using (mocks.Playback())
{
// return value should be added to cache
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(1, resultCache.Count);
Assert.AreEqual(returnValue, resultCache.Get("CacheResultWithMethodInfo-5"));
}
}
[Test]
@@ -434,44 +476,57 @@ namespace Spring.Aspects.Cache
MethodInfo method = new EnumerableResultMethod(cacheResultTarget.CacheResultItemsWithMethodInfo).Method;
object expectedReturnValue = new object[] { "one", "two", "three" };
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval("items", itemCache);
using (mocks.Record())
{
ExpectAttributeRetrieval(method);
ExpectCacheKeyGeneration(method, 5, expectedReturnValue);
ExpectCallToProceed(new object[] { "one", "two", "three" });
ExpectCacheInstanceRetrieval("items", itemCache);
}
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke((IMethodInvocation)mockInvocation.Object);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(0, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
Assert.AreEqual("two", itemCache.Get("CacheResultItemsWithMethodInfo-two"));
using (mocks.Playback())
{
// return value should be added to result cache and each item to item cache
object returnValue = advice.Invoke(mockInvocation);
Assert.AreEqual(expectedReturnValue, returnValue);
Assert.AreEqual(0, resultCache.Count);
Assert.AreEqual(3, itemCache.Count);
Assert.AreEqual("two", itemCache.Get("CacheResultItemsWithMethodInfo-two"));
}
mockInvocation.Verify();
mockContext.Verify();
}
#region Helper methods
private void ExpectAttributeRetrieval( MethodInfo method )
private void ExpectAttributeRetrieval(MethodInfo method)
{
mockInvocation.SetValue( "Method", method );
Expect.Call(mockInvocation.Method).Return(method).Repeat.AtLeastOnce();
}
private void ExpectCacheKeyGeneration( MethodInfo method, params object[] arguments )
private void ExpectCacheKeyGeneration(MethodInfo method, params object[] arguments)
{
// mockInvocation.ExpectAndReturn( "Method", method );
mockInvocation.SetValue( "Arguments", arguments );
Expect.Call(mockInvocation.Arguments).Return(arguments).Repeat.AtLeastOnce();
}
private void ExpectCacheInstanceRetrieval( string cacheName, ICache cache )
private void ExpectCacheInstanceRetrieval(string cacheName, ICache cache)
{
mockContext.ExpectAndReturn( "GetObject", cache, cacheName );
Expect.Call(mockContext.GetObject(cacheName)).Return(cache).Repeat.AtLeastOnce();
}
private void ExpectCallToProceed( object expectedReturnValue )
private void ExpectCacheInstanceRetrieval(string cacheName, ICache cache, int repeatTimes)
{
mockInvocation.ExpectAndReturn( "Proceed", expectedReturnValue );
Expect.Call(mockContext.GetObject(cacheName)).Return(cache).Repeat.Times(repeatTimes);
}
private void ExpectCallToProceed(object expectedReturnValue, int repeatTimes)
{
Expect.Call(mockInvocation.Proceed()).Return(expectedReturnValue).Repeat.Times(repeatTimes);
}
private void ExpectCallToProceed(object expectedReturnValue)
{
Expect.Call(mockInvocation.Proceed()).Return(expectedReturnValue);
}
#endregion
@@ -482,13 +537,13 @@ namespace Spring.Aspects.Cache
public delegate void VoidMethod();
public delegate int IntMethod();
public delegate IEnumerable EnumerableResultMethod( int key, params object[] elements );
public delegate IEnumerable EnumerableResultMethod(int key, params object[] elements);
public class EnumerableOnlyResult : IEnumerable
{
private object[] _args;
public EnumerableOnlyResult( params object[] args )
public EnumerableOnlyResult(params object[] args)
{
_args = args;
}
@@ -498,9 +553,9 @@ namespace Spring.Aspects.Cache
return _args.GetEnumerator();
}
public override bool Equals( object obj )
public override bool Equals(object obj)
{
Assert.AreEqual(_args, ((EnumerableOnlyResult)obj)._args );
Assert.AreEqual(_args, ((EnumerableOnlyResult)obj)._args);
return true;
}
@@ -526,55 +581,55 @@ namespace Spring.Aspects.Cache
{
void ReturnsNothing();
int ReturnsScalar();
IEnumerable ReturnsCollection( int key, params object[] elements );
IEnumerable ReturnsCollectionAndItems( int key, params object[] elements );
IEnumerable ReturnsItems( int key, params object[] elements );
IEnumerable ReturnsCollection(int key, params object[] elements);
IEnumerable ReturnsCollectionAndItems(int key, params object[] elements);
IEnumerable ReturnsItems(int key, params object[] elements);
}
public sealed class CacheResultTarget : ICacheResultTarget
{
public const int Scalar = int.MaxValue;
[CacheResult( "results", "'key'" )]
[CacheResult("results", "'key'")]
public void ReturnsNothing()
{
}
[CacheResult( "results", "'key'" )]
[CacheResult("results", "'key'")]
public int ReturnsScalar()
{
return Scalar;
}
[CacheResult( "results", "#key" )]
public IEnumerable ReturnsCollection( int key, params object[] elements )
[CacheResult("results", "#key")]
public IEnumerable ReturnsCollection(int key, params object[] elements)
{
return elements;
}
[CacheResult( "results", "#key" )]
[CacheResultItems( "items", "''+#this" )]
public IEnumerable ReturnsCollectionAndItems( int key, params object[] elements )
[CacheResult("results", "#key")]
[CacheResultItems("items", "''+#this")]
public IEnumerable ReturnsCollectionAndItems(int key, params object[] elements)
{
return elements;
}
[CacheResult( "results", "#key" )]
[CacheResultItems( "items", "''+#this" )]
public IEnumerable ReturnsEnumerableOnlyAndItems( int key, params object[] elements )
[CacheResult("results", "#key")]
[CacheResultItems("items", "''+#this")]
public IEnumerable ReturnsEnumerableOnlyAndItems(int key, params object[] elements)
{
return new EnumerableOnlyResult(elements);
}
[CacheResultItems( "items", "#this" )]
public IEnumerable ReturnsItems( int key, params object[] elements )
[CacheResultItems("items", "#this")]
public IEnumerable ReturnsItems(int key, params object[] elements)
{
return elements;
}
[CacheResultItems( "items", "#this" )]
[CacheResultItems( "items", "#this.ToUpper()" )]
public IEnumerable MultipleCacheResultItems( int key, params object[] elements )
[CacheResultItems("items", "#this")]
[CacheResultItems("items", "#this.ToUpper()")]
public IEnumerable MultipleCacheResultItems(int key, params object[] elements)
{
return elements;
}
@@ -591,14 +646,14 @@ namespace Spring.Aspects.Cache
return elements;
}
[CacheResultItems( "items", "#this", Condition = "#this.StartsWith('t')" )]
public IEnumerable CacheResultItemsWithCondition( int key, params object[] elements )
[CacheResultItems("items", "#this", Condition = "#this.StartsWith('t')")]
public IEnumerable CacheResultItemsWithCondition(int key, params object[] elements)
{
return elements;
}
[CacheResult( "results", "#key", Condition = "#this.Length > 0" )]
public IEnumerable CacheResultWithCondition( int key, params object[] elements )
[CacheResult("results", "#key", Condition = "#this.Length > 0")]
public IEnumerable CacheResultWithCondition(int key, params object[] elements)
{
return elements;
}
@@ -623,7 +678,7 @@ namespace Spring.Aspects.Cache
public override object Get(object key)
{
byte[] bytes = (byte[]) base.Get(key);
byte[] bytes = (byte[])base.Get(key);
if (bytes == null)
{

View File

@@ -22,7 +22,7 @@
using System;
using System.Reflection;
using DotNetMock.Dynamic;
using Rhino.Mocks;
using NUnit.Framework;
using Spring.Context;
using Spring.Validation;
@@ -39,17 +39,19 @@ namespace Spring.Aspects.Validation
[TestFixture]
public sealed class ParameterValidationAdviceTests
{
private IDynamicMock mockContext;
private IApplicationContext mockContext;
private ParameterValidationAdvice advice;
private RequiredValidator requiredValidator;
private MockRepository mocks;
[SetUp]
public void SetUp()
{
mockContext = new DynamicMock(typeof (IApplicationContext));
mocks = new MockRepository();
mockContext = mocks.CreateMock<IApplicationContext>();
advice = new ParameterValidationAdvice();
advice.ApplicationContext = (IApplicationContext) mockContext.Object;
advice.ApplicationContext = mockContext;
requiredValidator = new RequiredValidator();
requiredValidator.Actions.Add(new ErrorMessageAction("error.required", "errors"));
@@ -63,13 +65,18 @@ namespace Spring.Aspects.Validation
ValidationTarget target = new ValidationTarget();
object[] args = new object[] {inventor};
ExpectValidatorRetrieval("required", requiredValidator);
advice.Before(method, args, target);
method.Invoke(target, args);
using (mocks.Record())
{
ExpectValidatorRetrieval("required", requiredValidator);
}
Assert.AreEqual("NIKOLA TESLA", inventor.Name);
using (mocks.Playback())
{
advice.Before(method, args, target);
method.Invoke(target, args);
Assert.AreEqual("NIKOLA TESLA", inventor.Name);
}
mockContext.Verify();
}
[Test]
@@ -78,16 +85,22 @@ namespace Spring.Aspects.Validation
{
MethodInfo method = typeof(ValidationTarget).GetMethod("Save");
ExpectValidatorRetrieval("required", requiredValidator);
advice.Before(method, new object[] { null }, new ValidationTarget());
mockContext.Verify();
using (mocks.Record())
{
ExpectValidatorRetrieval("required", requiredValidator);
}
using (mocks.Playback())
{
advice.Before(method, new object[] { null }, new ValidationTarget());
}
}
#region Helper methods
private void ExpectValidatorRetrieval(string validatorName, IValidator validator)
{
mockContext.ExpectAndReturn("GetObject", validator, validatorName);
Expect.Call(mockContext.GetObject(validatorName)).Return(validator);
}
#endregion

View File

@@ -123,13 +123,23 @@ namespace Spring.Context.Support
return null;
}
public string[] GetObjectNamesForType(
public string[] GetObjectNamesForType<T>()
{
return null;
}
public string[] GetObjectNamesForType(
Type type, bool includePrototypes, bool includeFactoryObjects)
{
return null;
}
string[] IListableObjectFactory.GetObjectDefinitionNames()
public string[] GetObjectNamesForType<T>(bool includePrototypes, bool includeFactoryObjects)
{
return null;
}
string[] IListableObjectFactory.GetObjectDefinitionNames()
{
return null;
}
@@ -139,12 +149,27 @@ namespace Spring.Context.Support
return null;
}
public IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects)
public IDictionary GetObjectsOfType<T>()
{
return null;
}
public IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects)
{
return null;
}
public int ObjectDefinitionCount
public IDictionary GetObjectsOfType<T>(bool includePrototypes, bool includeFactoryObjects)
{
return null;
}
public T GetObject<T>()
{
throw new NotImplementedException();
}
public int ObjectDefinitionCount
{
get { return 0; }
}
@@ -178,12 +203,22 @@ namespace Spring.Context.Support
return null;
}
public bool IsTypeMatch<T>(string name)
{
return false;
}
public object CreateObject(string name, Type requiredType, object[] arguments)
{
return null;
}
public object GetObject(string name, Type requiredType)
public T CreateObject<T>(string name, object[] arguments)
{
return Activator.CreateInstance<T>();
}
public object GetObject(string name, Type requiredType)
{
return null;
}
@@ -193,11 +228,21 @@ namespace Spring.Context.Support
return null;
}
public T GetObject<T>(string name)
{
return Activator.CreateInstance<T>();
}
public object GetObject(string name, object[] arguments)
{
return null;
}
public T GetObject<T>(string name, object[] arguments)
{
return Activator.CreateInstance<T>();
}
public object GetObject(string name, Type requiredType, object[] arguments)
{
return null;