diff --git a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs index 483e557f..801c7d13 100644 --- a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs +++ b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs @@ -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); } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectNamesForType() + { + return GetObjectNamesForType(typeof(T)); + } + /// /// Return the names of objects matching the given /// (including subclasses), judging from the object definitions. @@ -1267,6 +1295,46 @@ namespace Spring.Context.Support return ObjectFactory.GetObjectNamesForType(type, includePrototypes, includeFactoryObjects); } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + /// Use + /// to include beans in ancestor factories too. + /// <p>Note: Does <i>not</i> ignore singleton objects that have been registered + /// by other means than bean definitions. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectNamesForType(bool includePrototypes, bool includeFactoryObjects) + { + return GetObjectNamesForType(typeof(T), includePrototypes, includeFactoryObjects); + } + /// /// Return the names of all objects defined in this factory. /// @@ -1350,6 +1418,38 @@ namespace Spring.Context.Support return GetObjectsOfType(type, true, true); } + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + ///

+ /// This version of the + /// method matches all kinds of object definitions, be they singletons, prototypes, or + /// s. Typically, the results + /// of this method call will be the same as a call to + /// IListableObjectFactory.GetObjectsOfType(type,true,true) . + ///

+ ///
+ /// + /// The (class or interface) to match. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + public IDictionary GetObjectsOfType() + { + return GetObjectsOfType(typeof(T)); + } + /// /// Return the object instances that match the given object /// (including subclasses), judging from either object @@ -1383,6 +1483,82 @@ namespace Spring.Context.Support return ObjectFactory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects); } + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + /// The (class or interface) to match. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + public IDictionary GetObjectsOfType(bool includePrototypes, bool includeFactoryObjects) + { + return GetObjectsOfType(typeof(T), includePrototypes, includeFactoryObjects); + } + + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The type of the object to return. + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If there is more than a single object of the requested type defined in the factory. + /// + /// + /// If the object could not be created. + /// + public T GetObject() + { + 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]); + } + /// /// Return the number of objects defined in the factory. /// @@ -1457,6 +1633,27 @@ namespace Spring.Context.Support } + /// + /// Determines whether the object with the given name matches the specified type. + /// + /// More specifically, check whether a GetObject call for the given name + /// would return an object that is assignable to the specified target type. + /// Translates aliases back to the corresponding canonical bean name. + /// Will ask the parent factory if the bean cannot be found in this factory instance. + /// + /// The name of the object to query. + /// Type of the target to match against. + /// + /// true if the object type matches; otherwise, false + /// if it doesn't match or cannot be determined yet. + /// + /// Ff there is no object with the given name + /// + public bool IsTypeMatch(string name) + { + return IsTypeMatch(name, typeof(T)); + } + /// /// Return an unconfigured(!) instance (possibly shared or independent) of the given object name. /// @@ -1495,6 +1692,44 @@ namespace Spring.Context.Support return ObjectFactory.CreateObject(name, requiredType, arguments); } + /// + /// Return an unconfigured(!) instance (possibly shared or independent) of the given object name. + /// + /// The name of the object to return. + /// + /// The the object may match. Can be an interface or + /// superclass of the actual class. For example, if the value is the + /// class, this method will succeed whatever the + /// class of the returned instance. + /// + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a factory method. If there is no factory method and the + /// supplied array is not , then + /// match the argument values by type and call the object's constructor. + /// + /// The unconfigured(!) instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + /// + /// + /// This method will only instantiate the requested object. It does NOT inject any dependencies! + /// + public T CreateObject(string name, object[] arguments) + { + return (T)CreateObject(name, typeof(T), arguments); + } + /// /// Return an instance (possibly shared or independent) of the given object name. /// @@ -1538,6 +1773,41 @@ namespace Spring.Context.Support return ObjectFactory.GetObject(name); } + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The type of the object to return. + /// The name of the object to return. + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the object could not be created. + /// + public T GetObject(string name) + { + return (T)GetObject(name, typeof(T)); + } + /// /// Return an instance (possibly shared or independent) of the given object name. /// @@ -1578,6 +1848,49 @@ namespace Spring.Context.Support return ObjectFactory.GetObject(name, arguments); } + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The name of the object to return. + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a static factory method. If there is no factory method and the + /// arguments are not null, then match the argument values by type and + /// call the object's constructor. + /// + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + public T GetObject(string name, object[] arguments) + { + return (T)GetObject(name, typeof(T), arguments); + } + /// /// Return an instance (possibly shared or independent) of the given object name. /// diff --git a/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs index 084c9027..2911d715 100644 --- a/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs @@ -120,6 +120,33 @@ namespace Spring.Objects.Factory /// string[] GetObjectNamesForType(Type type); + + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + string[] GetObjectNamesForType(); + + /// /// Return the names of objects matching the given /// (including subclasses), judging from the object definitions. @@ -157,6 +184,43 @@ namespace Spring.Objects.Factory /// string[] GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects); + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + /// Use + /// to include beans in ancestor factories too. + /// <p>Note: Does <i>not</i> ignore singleton objects that have been registered + /// by other means than bean definitions. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + string[] GetObjectNamesForType(bool includePrototypes, bool includeFactoryObjects); + /// /// Return the object instances that match the given object /// (including subclasses), judging from either object @@ -185,6 +249,35 @@ namespace Spring.Objects.Factory /// If the objects could not be created. /// IDictionary GetObjectsOfType(Type type); + + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + ///

+ /// This version of the + /// method matches all kinds of object definitions, be they singletons, prototypes, or + /// s. Typically, the results + /// of this method call will be the same as a call to + /// IListableObjectFactory.GetObjectsOfType(type,true,true) . + ///

+ ///
+ /// + /// The (class or interface) to match. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + IDictionary GetObjectsOfType(); /// /// Return the object instances that match the given object @@ -212,9 +305,65 @@ namespace Spring.Objects.Factory /// /// If the objects could not be created. /// - IDictionary GetObjectsOfType( - Type type, bool includePrototypes, bool includeFactoryObjects); + IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects); + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + /// The (class or interface) to match. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + IDictionary GetObjectsOfType(bool includePrototypes, bool includeFactoryObjects); + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The type of the object to return. + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If there is more than a single object of the requested type defined in the factory. + /// + /// + /// If the object could not be created. + /// + T GetObject(); } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/IObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/IObjectFactory.cs index 8f643188..dbfaadae 100644 --- a/src/Spring/Spring.Core/Objects/Factory/IObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/IObjectFactory.cs @@ -286,7 +286,39 @@ namespace Spring.Objects.Factory /// If the object could not be created. /// object GetObject(string name); - + + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The type of the object to return. + /// The name of the object to return. + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the object could not be created. + /// + T GetObject(string name); + /// /// Return an instance (possibly shared or independent) of the given object name. /// @@ -323,6 +355,46 @@ namespace Spring.Objects.Factory /// If the supplied is . /// object GetObject(string name, object[] arguments); + + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The name of the object to return. + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a static factory method. If there is no factory method and the + /// arguments are not null, then match the argument values by type and + /// call the object's constructor. + /// + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + T GetObject(string name, object[] arguments); /// /// Return an instance (possibly shared or independent) of the given object name. @@ -434,6 +506,24 @@ namespace Spring.Objects.Factory /// bool IsTypeMatch(string name, Type targetType); + /// + /// Determines whether the object with the given name matches the specified type. + /// + /// More specifically, check whether a GetObject call for the given name + /// would return an object that is assignable to the specified target type. + /// Translates aliases back to the corresponding canonical bean name. + /// Will ask the parent factory if the bean cannot be found in this factory instance. + /// + /// The name of the object to query. + /// Type of the target to match against. + /// + /// true if the object type matches; otherwise, false + /// if it doesn't match or cannot be determined yet. + /// + /// Ff there is no object with the given name + /// + bool IsTypeMatch(string name); + /// /// Return an unconfigured(!) instance (possibly shared or independent) of the given object name. /// @@ -469,6 +559,41 @@ namespace Spring.Objects.Factory /// object CreateObject(string name, Type requiredType, object[] arguments); + /// + /// Return an unconfigured(!) instance (possibly shared or independent) of the given object name. + /// + /// The name of the object to return. + /// + /// The the object may match. Can be an interface or + /// superclass of the actual class. For example, if the value is the + /// class, this method will succeed whatever the + /// class of the returned instance. + /// + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a factory method. If there is no factory method and the + /// supplied array is not , then + /// match the argument values by type and call the object's constructor. + /// + /// The unconfigured(!) instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + /// + /// + /// This method will only instantiate the requested object. It does NOT inject any dependencies! + /// + T CreateObject(string name, object[] arguments); + /// /// Injects dependencies into the supplied instance /// using the named object definition. diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs index f7e87e9a..ad19745b 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs @@ -266,6 +266,48 @@ namespace Spring.Objects.Factory.Support #region Methods + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The name of the object to return. + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a static factory method. If there is no factory method and the + /// arguments are not null, then match the argument values by type and + /// call the object's constructor. + /// + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + public T GetObject(string name, object[] arguments) + { + return (T)GetObject(name, typeof(T), arguments); + } /// /// Return an instance (possibly shared or independent) of the given object name. @@ -1266,6 +1308,27 @@ namespace Spring.Objects.Factory.Support } } + /// + /// Determines whether the object with the given name matches the specified type. + /// + /// More specifically, check whether a GetObject call for the given name + /// would return an object that is assignable to the specified target type. + /// Translates aliases back to the corresponding canonical bean name. + /// Will ask the parent factory if the bean cannot be found in this factory instance. + /// + /// The name of the object to query. + /// Type of the target to match against. + /// + /// true if the object type matches; otherwise, false + /// if it doesn't match or cannot be determined yet. + /// + /// Ff there is no object with the given name + /// + public bool IsTypeMatch(string name) + { + return IsTypeMatch(name, typeof (T)); + } + /// /// Determines the of the object with the /// supplied . @@ -1801,6 +1864,44 @@ namespace Spring.Objects.Factory.Support return GetObjectInternal(name, requiredType, arguments, true); } + /// + /// Return an unconfigured(!) instance (possibly shared or independent) of the given object name. + /// + /// The name of the object to return. + /// + /// The the object may match. Can be an interface or + /// superclass of the actual class. For example, if the value is the + /// class, this method will succeed whatever the + /// class of the returned instance. + /// + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a factory method. If there is no factory method and the + /// supplied array is not , then + /// match the argument values by type and call the object's constructor. + /// + /// The unconfigured(!) instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + /// + /// + /// This method will only instantiate the requested object. It does NOT inject any dependencies! + /// + public T CreateObject(string name, object[] arguments) + { + return (T)CreateObject(name, typeof(T), arguments); + } + /// /// Return an instance (possibly shared or independent) of the given object name. /// @@ -1810,6 +1911,41 @@ namespace Spring.Objects.Factory.Support return GetObjectInternal(name, null, null, false); } + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The type of the object to return. + /// The name of the object to return. + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the object could not be created. + /// + public T GetObject(string name) + { + return (T)GetObject(name); + } + /// /// Return an instance (possibly shared or independent) of the given object name. /// diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs index ccb7be7f..522ced09 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs @@ -662,6 +662,34 @@ namespace Spring.Objects.Factory.Support return GetObjectNamesForType(type, true, true); } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectNamesForType() + { + return GetObjectNamesForType(typeof (T)); + } + /// /// Return the names of objects matching the given /// (including subclasses), judging from the object definitions. @@ -690,6 +718,46 @@ namespace Spring.Objects.Factory.Support return (string[])ArrayList.Adapter(objectNames).ToArray(typeof(string)); } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + /// Use + /// to include beans in ancestor factories too. + /// <p>Note: Does <i>not</i> ignore singleton objects that have been registered + /// by other means than bean definitions. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectNamesForType(bool includePrototypes, bool includeFactoryObjects) + { + return GetObjectNamesForType(typeof (T), includePrototypes, includeFactoryObjects); + } + /// /// Return the object instances that match the given object /// (including subclasses), judging from either object @@ -714,6 +782,38 @@ namespace Spring.Objects.Factory.Support return GetObjectsOfType(type, true, true); } + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + ///

+ /// This version of the + /// method matches all kinds of object definitions, be they singletons, prototypes, or + /// s. Typically, the results + /// of this method call will be the same as a call to + /// IListableObjectFactory.GetObjectsOfType(type,true,true) . + ///

+ ///
+ /// + /// The (class or interface) to match. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + public IDictionary GetObjectsOfType() + { + return GetObjectsOfType(typeof (T)); + } + /// /// Return the object instances that match the given object /// (including subclasses). @@ -774,6 +874,82 @@ namespace Spring.Objects.Factory.Support return result; } + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + /// The (class or interface) to match. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + public IDictionary GetObjectsOfType(bool includePrototypes, bool includeFactoryObjects) + { + return GetObjectsOfType(typeof (T), includePrototypes, includeFactoryObjects); + } + + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The type of the object to return. + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If there is more than a single object of the requested type defined in the factory. + /// + /// + /// If the object could not be created. + /// + public T GetObject() + { + 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]); + } + /// /// Return the object instances that match the given object /// (including subclasses). diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs index 90b6fc3a..98ead8fd 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs @@ -28,342 +28,479 @@ using Spring.Util; namespace Spring.Objects.Factory.Support { - /// - /// Static factory that permits the registration of existing singleton instances. - /// - /// - ///

- /// Does not have support for prototype objects, aliases, and post startup object - /// configuration. - ///

- ///

- /// Serves as a simple example implementation of the - /// interface, that manages existing object instances as opposed to creating new ones - /// based on object definitions. - ///

- ///

- /// The - /// method is not supported by this class; this class deals exclusively with - /// existing singleton instances, thus the methods mentioned previously make little sense in this context. - ///

- ///
- /// Rod Johnson - /// Juergen Hoeller - /// Simon White (.NET) + /// + /// Static factory that permits the registration of existing singleton instances. + /// + /// + ///

+ /// Does not have support for prototype objects, aliases, and post startup object + /// configuration. + ///

+ ///

+ /// Serves as a simple example implementation of the + /// interface, that manages existing object instances as opposed to creating new ones + /// based on object definitions. + ///

+ ///

+ /// The + /// method is not supported by this class; this class deals exclusively with + /// existing singleton instances, thus the methods mentioned previously make little sense in this context. + ///

+ ///
+ /// Rod Johnson + /// Juergen Hoeller + /// Simon White (.NET) [Serializable] public class StaticListableObjectFactory : IListableObjectFactory - { - /// - /// Map from object name to object instance. - /// - private Hashtable objects = new Hashtable(); + { + /// + /// Map from object name to object instance. + /// + private Hashtable objects = new Hashtable(); - /// - /// Determine whether this object factory treats object names case-sensitive or not. - /// - public bool IsCaseSensitive - { - get { return true; } - } + /// + /// Determine whether this object factory treats object names case-sensitive or not. + /// + public bool IsCaseSensitive + { + get { return true; } + } - /// - /// Return the number of objects defined in the factory. - /// - /// - /// The number of objects defined in the factory. - /// - public int ObjectDefinitionCount - { - get { return objects.Count; } - } + /// + /// Return the number of objects defined in the factory. + /// + /// + /// The number of objects defined in the factory. + /// + public int ObjectDefinitionCount + { + get { return objects.Count; } + } - /// - /// Return an instance of the given object name. - /// - /// The name of the object to return. - /// The instance of the object. - /// - public object this[string name] - { - get { return GetObject(name); } - } + /// + /// Return an instance of the given object name. + /// + /// The name of the object to return. + /// The instance of the object. + /// + public object this[string name] + { + get { return GetObject(name); } + } - /// - /// This method is not supported by . - /// - /// - public object CreateObject(string name, Type requiredType, object[] arguments) - { - throw new NotSupportedException("StaticListableObjectFactory does not support this method."); - } + /// + /// Determines whether the object with the given name matches the specified type. + /// + /// More specifically, check whether a GetObject call for the given name + /// would return an object that is assignable to the specified target type. + /// Translates aliases back to the corresponding canonical bean name. + /// Will ask the parent factory if the bean cannot be found in this factory instance. + /// + /// The name of the object to query. + /// Type of the target to match against. + /// + /// true if the object type matches; otherwise, false + /// if it doesn't match or cannot be determined yet. + /// + /// Ff there is no object with the given name + /// + public bool IsTypeMatch(string name) + { + return IsTypeMatch(name, typeof(T)); + } - /// - /// Return an instance of the given object name. - /// - /// The name of the object to return. - /// The instance of the object. + /// + /// This method is not supported by . + /// + /// + public object CreateObject(string name, Type requiredType, object[] arguments) + { + throw new NotSupportedException("StaticListableObjectFactory does not support this method."); + } + + /// + /// Return an unconfigured(!) instance (possibly shared or independent) of the given object name. + /// + /// The name of the object to return. + /// + /// The the object may match. Can be an interface or + /// superclass of the actual class. For example, if the value is the + /// class, this method will succeed whatever the + /// class of the returned instance. + /// + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a factory method. If there is no factory method and the + /// supplied array is not , then + /// match the argument values by type and call the object's constructor. + /// + /// The unconfigured(!) instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + /// + /// + /// This method will only instantiate the requested object. It does NOT inject any dependencies! + /// + public T CreateObject(string name, object[] arguments) + { + return (T)CreateObject(name, typeof(T), arguments); + } + + /// + /// Return an instance of the given object name. + /// + /// The name of the object to return. + /// The instance of the object. /// /// is not currently supported. /// - /// - public object GetObject(string name) - { - object instance = objects[name]; - if (instance is IFactoryObject) - { + /// + public object GetObject(string name) + { + object instance = objects[name]; + if (instance is IFactoryObject) + { if (instance is IConfigurableFactoryObject) { throw new NotSupportedException(); } - try - { - return ((IFactoryObject) instance).GetObject(); - } - catch (Exception ex) - { - throw new ObjectCreationException(name, - "IFactoryObject threw an exception on object creation", ex); - } - } - if (instance == null) - { - throw new NoSuchObjectDefinitionException(name, GrabDefinedObjectsString()); - } - return instance; - } + try + { + return ((IFactoryObject)instance).GetObject(); + } + catch (Exception ex) + { + throw new ObjectCreationException(name, + "IFactoryObject threw an exception on object creation", ex); + } + } + if (instance == null) + { + throw new NoSuchObjectDefinitionException(name, GrabDefinedObjectsString()); + } + return instance; + } - /// - /// Return an instance (possibly shared or independent) of the given object name. - /// - /// - ///

- /// This method allows an object factory to be used as a replacement for the - /// Singleton or Prototype design pattern. - ///

- ///

- /// Note that callers should retain references to returned objects. There is no - /// guarantee that this method will be implemented to be efficient. For example, - /// it may be synchronized, or may need to run an RDBMS query. - ///

- ///

- /// Will ask the parent factory if the object cannot be found in this factory - /// instance. - ///

- ///
- /// The name of the object to return. - /// - /// The arguments to use if creating a prototype using explicit arguments to - /// a static factory method. If there is no factory method and the - /// arguments are not null, then match the argument values by type and - /// call the object's constructor. - /// - /// The instance of the object. - /// - /// If there's no such object definition. - /// - /// - /// If the object could not be created. - /// - /// - /// If the supplied is . - /// - public object GetObject(string name, object[] arguments) - { - throw new NotSupportedException("StaticListableObjectFactory does not support this method."); - } + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The type of the object to return. + /// The name of the object to return. + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the object could not be created. + /// + public T GetObject(string name) + { + return (T)GetObject(name, typeof(T)); + } - /// - /// Return an instance (possibly shared or independent) of the given object name. - /// - /// The name of the object to return. - /// - /// The the object may match. Can be an interface or - /// superclass of the actual class. For example, if the value is the - /// class, this method will succeed whatever the - /// class of the returned instance. - /// - /// - /// The arguments to use if creating a prototype using explicit arguments to - /// a factory method. If there is no factory method and the - /// supplied array is not , then - /// match the argument values by type and call the object's constructor. - /// - /// The instance of the object. - /// - /// If there's no such object definition. - /// - /// - /// If the object could not be created. - /// - /// - /// If the object is not of the required type. - /// - /// - /// If the supplied is . - /// - /// - public object GetObject(string name, Type requiredType, object[] arguments) - { - throw new NotSupportedException("StaticListableObjectFactory does not support this method."); - } + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + ///

+ /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + ///

+ ///

+ /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + ///

+ ///

+ /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + ///

+ ///
+ /// The name of the object to return. + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a static factory method. If there is no factory method and the + /// arguments are not null, then match the argument values by type and + /// call the object's constructor. + /// + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the supplied is . + /// + public object GetObject(string name, object[] arguments) + { + throw new NotSupportedException("StaticListableObjectFactory does not support this method."); + } - /// - /// Return an instance of the given object name. - /// - /// The name of the object to return. - /// - /// the object may match. Can be an interface or - /// superclass of the actual class. For example, if the value is the - /// class, this method will succeed whatever the - /// class of the returned instance. - /// - /// The instance of the object. - /// - public object GetObject(string name, Type requiredType) - { - object instance = GetObject(name); - if (!requiredType.IsAssignableFrom(instance.GetType())) - { - throw new ObjectNotOfRequiredTypeException(name, requiredType, instance); - } - return instance; - } + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The name of the object to return. + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a static factory method. If there is no factory method and the + /// arguments are not null, then match the argument values by type and + /// call the object's constructor. + /// + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + public T GetObject(string name, object[] arguments) + { + return (T)GetObject(name, typeof(T), arguments); + } - /// - /// Does this object factory contain an object with the given name? - /// - /// The name of the object to query. - /// True if an object with the given name is defined. - public bool ContainsObject(string name) - { - return objects.ContainsKey(name); - } + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// The name of the object to return. + /// + /// The the object may match. Can be an interface or + /// superclass of the actual class. For example, if the value is the + /// class, this method will succeed whatever the + /// class of the returned instance. + /// + /// + /// The arguments to use if creating a prototype using explicit arguments to + /// a factory method. If there is no factory method and the + /// supplied array is not , then + /// match the argument values by type and call the object's constructor. + /// + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If the object could not be created. + /// + /// + /// If the object is not of the required type. + /// + /// + /// If the supplied is . + /// + /// + public object GetObject(string name, Type requiredType, object[] arguments) + { + throw new NotSupportedException("StaticListableObjectFactory does not support this method."); + } - /// - /// Is this object a singleton? - /// - /// - ///

- /// That is, will + ///

+ /// Return an instance of the given object name. + /// + /// The name of the object to return. + /// + /// the object may match. Can be an interface or + /// superclass of the actual class. For example, if the value is the + /// class, this method will succeed whatever the + /// class of the returned instance. + /// + /// The instance of the object. + /// + public object GetObject(string name, Type requiredType) + { + object instance = GetObject(name); + if (!requiredType.IsAssignableFrom(instance.GetType())) + { + throw new ObjectNotOfRequiredTypeException(name, requiredType, instance); + } + return instance; + } + + /// + /// Does this object factory contain an object with the given name? + /// + /// The name of the object to query. + /// True if an object with the given name is defined. + public bool ContainsObject(string name) + { + return objects.ContainsKey(name); + } + + /// + /// Is this object a singleton? + /// + /// + ///

+ /// That is, will /// or - /// always return the same object? - ///

- ///
- /// The name of the object to query. - /// True if the named object is a singleton. - /// - /// If there's no such object definition. - /// - public bool IsSingleton(string name) - { - bool isSingleton = true; - object instance = GetObject(name); - // in case of IFactoryObject, return singleton status of created object - if (instance is IFactoryObject) - { - isSingleton = ((IFactoryObject) instance).IsSingleton; - } - return isSingleton; - } - - - /// - /// Determines whether the specified object name is prototype. That is, will GetObject - /// always return independent instances? - /// - /// This method returning false does not clearly indicate a singleton object. - /// It indicated non-independent instances, which may correspond to a scoped object as - /// well. use the IsSingleton property to explicitly check for a shared - /// singleton instance. - /// Translates aliases back to the corresponding canonical object name. Will ask the - /// parent factory if the object can not be found in this factory instance. - /// - /// - /// - /// The name of the object to query - /// - /// true if the specified object name will always deliver independent instances; otherwise, false. - /// - /// if there is no object with the given name. - public bool IsPrototype(string name) - { - bool isPrototype = true; - object instance = GetObject(name); + /// always return the same object? + ///

+ ///
+ /// The name of the object to query. + /// True if the named object is a singleton. + /// + /// If there's no such object definition. + /// + public bool IsSingleton(string name) + { + bool isSingleton = true; + object instance = GetObject(name); + // in case of IFactoryObject, return singleton status of created object if (instance is IFactoryObject) { - isPrototype = !((IFactoryObject) instance).IsSingleton; + isSingleton = ((IFactoryObject)instance).IsSingleton; } - return isPrototype; - - } - - /// - /// Determine the type of the object with the given name. - /// - /// - ///

- /// More specifically, checks the type of object that - /// would return. - /// For an , returns the type - /// of object that the creates. - ///

- ///
- /// The name of the object to query. - /// - /// The of the object or if - /// not determinable. - /// - public Type GetType(string name) - { - string objectName = ObjectFactoryUtils.TransformedObjectName(name); - object instance = objects[objectName]; - if (instance == null) - { - throw new NoSuchObjectDefinitionException(name, GrabDefinedObjectsString()); - } - if (instance is IFactoryObject && !ObjectFactoryUtils.IsFactoryDereference(name)) - { - return ((IFactoryObject) instance).ObjectType; - } - return instance.GetType(); - } + return isSingleton; + } - /// - /// Determines whether the object with the given name matches the specified type. - /// - /// The name of the object to query. - /// Type of the target to match against. - /// - /// true if the object type matches; otherwise, false - /// if it doesn't match or cannot be determined yet. - /// - /// Ff there is no object with the given name - /// - public bool IsTypeMatch(string name, Type targetType) - { - Type type = GetType(name); + /// + /// Determines whether the specified object name is prototype. That is, will GetObject + /// always return independent instances? + /// + /// This method returning false does not clearly indicate a singleton object. + /// It indicated non-independent instances, which may correspond to a scoped object as + /// well. use the IsSingleton property to explicitly check for a shared + /// singleton instance. + /// Translates aliases back to the corresponding canonical object name. Will ask the + /// parent factory if the object can not be found in this factory instance. + /// + /// + /// + /// The name of the object to query + /// + /// true if the specified object name will always deliver independent instances; otherwise, false. + /// + /// if there is no object with the given name. + public bool IsPrototype(string name) + { + bool isPrototype = true; + object instance = GetObject(name); + if (instance is IFactoryObject) + { + isPrototype = !((IFactoryObject)instance).IsSingleton; + } + return isPrototype; + + } + + /// + /// Determine the type of the object with the given name. + /// + /// + ///

+ /// More specifically, checks the type of object that + /// would return. + /// For an , returns the type + /// of object that the creates. + ///

+ ///
+ /// The name of the object to query. + /// + /// The of the object or if + /// not determinable. + /// + public Type GetType(string name) + { + string objectName = ObjectFactoryUtils.TransformedObjectName(name); + object instance = objects[objectName]; + if (instance == null) + { + throw new NoSuchObjectDefinitionException(name, GrabDefinedObjectsString()); + } + if (instance is IFactoryObject && !ObjectFactoryUtils.IsFactoryDereference(name)) + { + return ((IFactoryObject)instance).ObjectType; + } + return instance.GetType(); + } + + + /// + /// Determines whether the object with the given name matches the specified type. + /// + /// The name of the object to query. + /// Type of the target to match against. + /// + /// true if the object type matches; otherwise, false + /// if it doesn't match or cannot be determined yet. + /// + /// Ff there is no object with the given name + /// + public bool IsTypeMatch(string name, Type targetType) + { + Type type = GetType(name); return (targetType == null || (type != null && targetType.IsAssignableFrom(type))); - } + } - private string GrabDefinedObjectsString() - { - return "Defined objects are [" + - StringUtils.CollectionToDelimitedString(objects.Keys, ",") + "]"; - } + private string GrabDefinedObjectsString() + { + return "Defined objects are [" + + StringUtils.CollectionToDelimitedString(objects.Keys, ",") + "]"; + } - /// - /// Return the aliases for the given object name, if defined. - /// - /// The object name to check for aliases. - /// The aliases, or an empty array if none. - /// - /// If there's no such object definition. - /// - public string[] GetAliases(string name) - { - return StringUtils.EmptyStrings; - } + /// + /// Return the aliases for the given object name, if defined. + /// + /// The object name to check for aliases. + /// The aliases, or an empty array if none. + /// + /// If there's no such object definition. + /// + public string[] GetAliases(string name) + { + return StringUtils.EmptyStrings; + } /// /// Not supported. @@ -407,276 +544,452 @@ namespace Spring.Objects.Factory.Support /// - /// Return the names of all objects defined in this factory. - /// - /// - /// The names of all objects defined in this factory, or an empty array if none - /// are defined. - /// - public string[] GetObjectDefinitionNames() - { - ArrayList names = new ArrayList(objects.Keys); - return (string[]) names.ToArray(typeof (string)); - } + /// Return the names of all objects defined in this factory. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectDefinitionNames() + { + ArrayList names = new ArrayList(objects.Keys); + return (string[])names.ToArray(typeof(string)); + } - /// - /// Return the names of objects matching the given - /// (including subclasses), judging from the object definitions. - /// - /// - /// The (class or interface) to match, or - /// for all object names. - /// - /// - ///

- /// Will not consider s, - /// as the type of their created objects is not known before instantiation. - ///

- ///
- /// - /// The names of all objects defined in this factory, or an empty array if none - /// are defined. - /// - public string[] GetObjectDefinitionNames(Type type) - { - ArrayList matches = new ArrayList(); - foreach (string name in objects.Keys) - { - Type t = objects[name].GetType(); - if (type.IsAssignableFrom(t)) - { - matches.Add(name); - } - } - return (string[]) matches.ToArray(typeof (string)); - } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + ///

+ /// Will not consider s, + /// as the type of their created objects is not known before instantiation. + ///

+ ///
+ /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectDefinitionNames(Type type) + { + ArrayList matches = new ArrayList(); + foreach (string name in objects.Keys) + { + Type t = objects[name].GetType(); + if (type.IsAssignableFrom(t)) + { + matches.Add(name); + } + } + return (string[])matches.ToArray(typeof(string)); + } - /// - /// Return the names of objects matching the given - /// (including subclasses), judging from the object definitions. - /// - /// - /// The (class or interface) to match, or - /// for all object names. - /// - /// - ///

- /// Does consider objects created by s, - /// or rather it considers the type of objects created by - /// (which means that - /// s will be instantiated). - ///

- ///

- /// Does not consider any hierarchy this factory may participate in. - ///

- ///
- /// - /// The names of all objects defined in this factory, or an empty array if none - /// are defined. - /// - public string[] GetObjectNamesForType(Type type) - { - return GetObjectNamesForType(type, true, true); - } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + ///

+ ///
+ /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectNamesForType(Type type) + { + return GetObjectNamesForType(type, true, true); + } - /// - /// Return the names of objects matching the given - /// (including subclasses), judging from the object definitions. - /// - /// - ///

- /// Since this implementation of the - /// - /// interface does not support the notion of ptototype objects, the - /// parameter is ignored. - ///

- ///
- /// - /// The (class or interface) to match, or - /// for all object names. - /// - /// - /// Whether to include prototype objects too or just singletons (also applies to - /// s). Ignored. - /// - /// - /// Whether to include s too - /// or just normal objects. - /// - /// - /// The names of all objects defined in this factory, or an empty array if none - /// are defined. - /// - /// - public string[] GetObjectNamesForType( - Type type, bool includePrototypes, bool includeFactoryObjects) - { - bool isFactoryType = (type != null && typeof(IFactoryObject).IsAssignableFrom(type)); - IList matches = new ArrayList(); - foreach (string name in objects.Keys) - { - object instance = objects[name]; - if (instance is IFactoryObject && !isFactoryType) - { - if(includeFactoryObjects) - { - Type objectType = ((IFactoryObject) instance).ObjectType; - if (objectType != null && type.IsAssignableFrom(objectType)) - { - matches.Add(name); - } - } - } - else - { - if (type.IsInstanceOfType(instance)) - { - matches.Add(name); - } - } - } - return (string[]) ArrayList.Adapter(matches).ToArray(typeof(string)); - } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectNamesForType() + { + return GetObjectNamesForType(typeof(T)); + } - /// - /// Tests whether this object factory contains an object definition for the - /// specified object name. - /// - /// The object name to query. - /// - /// True if an object defintion is contained within this object factory. - /// - public bool ContainsObjectDefinition(string name) - { - return objects.ContainsKey(name); - } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Since this implementation of the + /// + /// interface does not support the notion of ptototype objects, the + /// parameter is ignored. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). Ignored. + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + /// + public string[] GetObjectNamesForType( + Type type, bool includePrototypes, bool includeFactoryObjects) + { + bool isFactoryType = (type != null && typeof(IFactoryObject).IsAssignableFrom(type)); + IList matches = new ArrayList(); + foreach (string name in objects.Keys) + { + object instance = objects[name]; + if (instance is IFactoryObject && !isFactoryType) + { + if (includeFactoryObjects) + { + Type objectType = ((IFactoryObject)instance).ObjectType; + if (objectType != null && type.IsAssignableFrom(objectType)) + { + matches.Add(name); + } + } + } + else + { + if (type.IsInstanceOfType(instance)) + { + matches.Add(name); + } + } + } + return (string[])ArrayList.Adapter(matches).ToArray(typeof(string)); + } - /// - /// Return the object instances that match the given object - /// (including subclasses), judging from either object - /// definitions or the value of - /// in the case of - /// s. - /// - /// - ///

- /// This version of the - /// method matches all kinds of object definitions, be they singletons, prototypes, or - /// s. Typically, the results - /// of this method call will be the same as a call to - /// IListableObjectFactory.GetObjectsOfType(type,true,true) . - ///

- ///
- /// - /// The (class or interface) to match. - /// - /// - /// A of the matching objects, - /// containing the object names as keys and the corresponding object instances - /// as values. - /// - /// - /// If the objects could not be created. - /// - public IDictionary GetObjectsOfType(Type type) - { - return GetObjectsOfType(type, true, true); - } + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + /// Use + /// to include beans in ancestor factories too. + /// <p>Note: Does <i>not</i> ignore singleton objects that have been registered + /// by other means than bean definitions. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + public string[] GetObjectNamesForType(bool includePrototypes, bool includeFactoryObjects) + { + return GetObjectNamesForType(typeof(T), includePrototypes, includeFactoryObjects); + } - /// - /// Return the object instances that match the given object - /// (including subclasses), judging from either object - /// definitions or the value of - /// in the case of - /// s. - /// - /// - /// The (class or interface) to match. - /// - /// - /// Whether to include prototype objects too or just singletons (also applies to - /// s). - /// - /// - /// Whether to include s too - /// or just normal objects. - /// - /// - /// A of the matching objects, - /// containing the object names as keys and the corresponding object instances - /// as values. - /// - /// - /// If the objects could not be created. - /// - public IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) - { - bool isFactoryType = (type != null && typeof(IFactoryObject).IsAssignableFrom(type)); - IDictionary matches = new Hashtable(); - foreach (string name in objects.Keys) - { - object instance = objects[name]; - if (instance is IFactoryObject && includeFactoryObjects) - { - IFactoryObject factory = (IFactoryObject) instance; - Type objectType = factory.ObjectType; - if ((objectType == null && factory.IsSingleton) || - ((factory.IsSingleton || includePrototypes) && - objectType != null && type.IsAssignableFrom(objectType))) - { - object createdObject = GetObject(name); - if (type.IsInstanceOfType(createdObject)) - { - matches[name] = createdObject; - } - } - } - else if (type.IsAssignableFrom(instance.GetType())) - { - if (isFactoryType) - { - matches[ObjectFactoryUtils.BuildFactoryObjectName(name)] = instance; - } - else - { - matches[name] = instance; - } - } - } - return matches; - } + /// + /// Tests whether this object factory contains an object definition for the + /// specified object name. + /// + /// The object name to query. + /// + /// True if an object defintion is contained within this object factory. + /// + public bool ContainsObjectDefinition(string name) + { + return objects.ContainsKey(name); + } - /// - /// Add a new singleton object. - /// - /// - /// The name to be associated with the object name. - /// - /// The singleton object. - public void AddObject(string name, object instance) - { - objects[name] = instance; - } + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + ///

+ /// This version of the + /// method matches all kinds of object definitions, be they singletons, prototypes, or + /// s. Typically, the results + /// of this method call will be the same as a call to + /// IListableObjectFactory.GetObjectsOfType(type,true,true) . + ///

+ ///
+ /// + /// The (class or interface) to match. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + public IDictionary GetObjectsOfType(Type type) + { + return GetObjectsOfType(type, true, true); + } - /// - /// Injects dependencies into the supplied instance - /// using the named object definition. - /// - /// - /// The object instance that is to be so configured. - /// - /// - /// The name of the object definition expressing the dependencies that are to - /// be injected into the supplied instance. + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + ///

+ /// This version of the + /// method matches all kinds of object definitions, be they singletons, prototypes, or + /// s. Typically, the results + /// of this method call will be the same as a call to + /// IListableObjectFactory.GetObjectsOfType(type,true,true) . + ///

+ ///
+ /// + /// The (class or interface) to match. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + public IDictionary GetObjectsOfType() + { + return GetObjectsOfType(typeof(T)); + } + + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + /// The (class or interface) to match. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + public IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) + { + bool isFactoryType = (type != null && typeof(IFactoryObject).IsAssignableFrom(type)); + IDictionary matches = new Hashtable(); + foreach (string name in objects.Keys) + { + object instance = objects[name]; + if (instance is IFactoryObject && includeFactoryObjects) + { + IFactoryObject factory = (IFactoryObject)instance; + Type objectType = factory.ObjectType; + if ((objectType == null && factory.IsSingleton) || + ((factory.IsSingleton || includePrototypes) && + objectType != null && type.IsAssignableFrom(objectType))) + { + object createdObject = GetObject(name); + if (type.IsInstanceOfType(createdObject)) + { + matches[name] = createdObject; + } + } + } + else if (type.IsAssignableFrom(instance.GetType())) + { + if (isFactoryType) + { + matches[ObjectFactoryUtils.BuildFactoryObjectName(name)] = instance; + } + else + { + matches[name] = instance; + } + } + } + return matches; + } + + /// + /// Return the object instances that match the given object + /// (including subclasses), judging from either object + /// definitions or the value of + /// in the case of + /// s. + /// + /// + /// The (class or interface) to match. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// A of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If the objects could not be created. + /// + public IDictionary GetObjectsOfType(bool includePrototypes, bool includeFactoryObjects) + { + return GetObjectsOfType(typeof(T), includePrototypes, includeFactoryObjects); + } + + /// + /// Return an instance (possibly shared or independent) of the given object name. + /// + /// + /// + /// This method allows an object factory to be used as a replacement for the + /// Singleton or Prototype design pattern. + /// + /// + /// Note that callers should retain references to returned objects. There is no + /// guarantee that this method will be implemented to be efficient. For example, + /// it may be synchronized, or may need to run an RDBMS query. + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The type of the object to return. + /// The instance of the object. + /// + /// If there's no such object definition. + /// + /// + /// If there is more than a single object of the requested type defined in the factory. + /// + /// + /// If the object could not be created. + /// + public T GetObject() + { + 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]); + } + + /// + /// Add a new singleton object. + /// + /// + /// The name to be associated with the object name. + /// + /// The singleton object. + public void AddObject(string name, object instance) + { + objects[name] = instance; + } + + /// + /// Injects dependencies into the supplied instance + /// using the named object definition. + /// + /// + /// The object instance that is to be so configured. + /// + /// + /// The name of the object definition expressing the dependencies that are to + /// be injected into the supplied instance. /// /// /// This feature is not currently supported. /// - /// - public object ConfigureObject(object target, string name) - { - throw new NotSupportedException(); - } + /// + public object ConfigureObject(object target, string name) + { + throw new NotSupportedException(); + } /// /// Injects dependencies into the supplied instance @@ -698,11 +1011,11 @@ namespace Spring.Objects.Factory.Support throw new NotSupportedException(); } - /// - /// Defines a method to release allocated unmanaged resources. - /// - public virtual void Dispose() - { - } - } + /// + /// Defines a method to release allocated unmanaged resources. + /// + public virtual void Dispose() + { + } + } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Util/ReflectionUtils.cs b/src/Spring/Spring.Core/Util/ReflectionUtils.cs index 5a1f6516..7b7d1cdc 100644 --- a/src/Spring/Spring.Core/Util/ReflectionUtils.cs +++ b/src/Spring/Spring.Core/Util/ReflectionUtils.cs @@ -125,16 +125,80 @@ namespace Spring.Util /// The target method. /// public static MethodInfo GetMethod( - Type targetType, string method, Type[] argumentTypes) + Type targetType, string method, Type[] argumentTypes) + { + return GetMethod(targetType, method, argumentTypes, 0); + } + + /// + /// Returns method for the specified , method + /// name and argument + /// s. + /// + /// + /// Searches with BindingFlags + /// When dealing with interface methods, you probable want to 'normalize' method references by calling + /// . + /// + /// + /// + /// The target to find the method on. + /// + /// The method to find. + /// + /// The argument s. May be + /// if the method has no arguments. + /// + /// Number of Generic Arguments in the method + /// The target method. + /// + 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(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 /// diff --git a/src/Spring/Spring.Services/ServiceModel/Support/ServiceProxyTypeBuilder.cs b/src/Spring/Spring.Services/ServiceModel/Support/ServiceProxyTypeBuilder.cs index 5f56f052..5ab31eae 100644 --- a/src/Spring/Spring.Services/ServiceModel/Support/ServiceProxyTypeBuilder.cs +++ b/src/Spring/Spring.Services/ServiceModel/Support/ServiceProxyTypeBuilder.cs @@ -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(); diff --git a/test/Spring/Spring.Aop.Tests/Aop/Target/PrototypeTargetSourceTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Target/PrototypeTargetSourceTests.cs index 47a56635..29181ec4 100644 --- a/test/Spring/Spring.Aop.Tests/Aop/Target/PrototypeTargetSourceTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aop/Target/PrototypeTargetSourceTests.cs @@ -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 { - /// - /// Unit tests for the PrototypeTargetSource class. - /// - /// Rod Johnson - /// Federico Spinazzi - [TestFixture] - public sealed class PrototypeTargetSourceTests - { - /// - /// The setup logic executed before the execution of this test fixture. - /// - [TestFixtureSetUp] - public void FixtureSetUp() - { - // enable (null appender) logging, just to ensure that the logging code is correct - LogManager.Adapter = new NoOpLoggerFactoryAdapter(); - } + /// + /// Unit tests for the PrototypeTargetSource class. + /// + /// Rod Johnson + /// Federico Spinazzi + [TestFixture] + public sealed class PrototypeTargetSourceTests + { + /// + /// The setup logic executed before the execution of this test fixture. + /// + [TestFixtureSetUp] + public void FixtureSetUp() + { + // enable (null appender) logging, just to ensure that the logging code is correct + LogManager.Adapter = new NoOpLoggerFactoryAdapter(); + } /// /// 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(); - [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(); + 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(delegate { source.ObjectFactory = factory; }); + } + } + + [Test] + public void GetTarget() + { + MockRepository mocks = new MockRepository(); + + IObjectFactory factory = mocks.CreateMock(); + 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(); + } + } } \ No newline at end of file diff --git a/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheResultAdviceTests.cs b/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheResultAdviceTests.cs index 240dd047..b3060b65 100644 --- a/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheResultAdviceTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aspects/Cache/CacheResultAdviceTests.cs @@ -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(); + mockContext = mocks.CreateMock(); 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) { diff --git a/test/Spring/Spring.Aop.Tests/Aspects/Validation/ParameterValidationAdviceTests.cs b/test/Spring/Spring.Aop.Tests/Aspects/Validation/ParameterValidationAdviceTests.cs index 079eb12b..4d7cb60a 100644 --- a/test/Spring/Spring.Aop.Tests/Aspects/Validation/ParameterValidationAdviceTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aspects/Validation/ParameterValidationAdviceTests.cs @@ -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(); 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 diff --git a/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs b/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs index 5afd3c71..468e6e09 100644 --- a/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs +++ b/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs @@ -123,13 +123,23 @@ namespace Spring.Context.Support return null; } - public string[] GetObjectNamesForType( + public string[] GetObjectNamesForType() + { + return null; + } + + public string[] GetObjectNamesForType( Type type, bool includePrototypes, bool includeFactoryObjects) { return null; } - string[] IListableObjectFactory.GetObjectDefinitionNames() + public string[] GetObjectNamesForType(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() + { + return null; + } + + public IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) { return null; } - public int ObjectDefinitionCount + public IDictionary GetObjectsOfType(bool includePrototypes, bool includeFactoryObjects) + { + return null; + } + + public T GetObject() + { + throw new NotImplementedException(); + } + + public int ObjectDefinitionCount { get { return 0; } } @@ -178,12 +203,22 @@ namespace Spring.Context.Support return null; } + public bool IsTypeMatch(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(string name, object[] arguments) + { + return Activator.CreateInstance(); + } + + public object GetObject(string name, Type requiredType) { return null; } @@ -193,11 +228,21 @@ namespace Spring.Context.Support return null; } + public T GetObject(string name) + { + return Activator.CreateInstance(); + } + public object GetObject(string name, object[] arguments) { return null; } + public T GetObject(string name, object[] arguments) + { + return Activator.CreateInstance(); + } + public object GetObject(string name, Type requiredType, object[] arguments) { return null;