diff --git a/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs b/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs index b0ec3266..6df7b471 100644 --- a/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs +++ b/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs @@ -30,55 +30,55 @@ using Spring.Util; namespace Spring.Objects.Factory { - /// - /// Convenience methods operating on object factories, returning object instances, - /// names, or counts. - /// - /// - ///

- /// The nesting hierarchy of an object factory is taken into account by the various methods - /// exposed by this class. - ///

- ///
- /// Rod Johnson - /// Juergen Hoeller - /// Rick Evans (.NET) - public sealed class ObjectFactoryUtils - { - #region Constructor (s) / Destructor + /// + /// Convenience methods operating on object factories, returning object instances, + /// names, or counts. + /// + /// + ///

+ /// The nesting hierarchy of an object factory is taken into account by the various methods + /// exposed by this class. + ///

+ ///
+ /// Rod Johnson + /// Juergen Hoeller + /// Rick Evans (.NET) + public sealed class ObjectFactoryUtils + { + #region Constructor (s) / Destructor - // CLOVER:OFF + // CLOVER:OFF - /// - /// Creates a new instance of the - /// class. - /// - /// - ///

- /// This is a utility class, and as such has no publicly visible - /// constructors. - ///

- ///
- private ObjectFactoryUtils() - { - } + /// + /// Creates a new instance of the + /// class. + /// + /// + ///

+ /// This is a utility class, and as such has no publicly visible + /// constructors. + ///

+ ///
+ private ObjectFactoryUtils() + { + } - // CLOVER:ON + // CLOVER:ON - #endregion + #endregion - /// - /// Used to dereference an - /// and distinguish it from managed objects created by the factory. - /// - /// - ///

- /// For example, if the managed object identified as foo is a - /// factory, getting &foo will return the factory, not the - /// instance returned by the factory. - ///

- ///
- public const string FactoryObjectPrefix = "&"; + /// + /// Used to dereference an + /// and distinguish it from managed objects created by the factory. + /// + /// + ///

+ /// For example, if the managed object identified as foo is a + /// factory, getting &foo will return the factory, not the + /// instance returned by the factory. + ///

+ ///
+ public const string FactoryObjectPrefix = "&"; /// /// The string used as a separator in the generation of synthetic id's @@ -93,105 +93,94 @@ namespace Spring.Objects.Factory /// public const string GENERATED_OBJECT_NAME_SEPARATOR = "#"; - /// - /// Count all object definitions in any hierarchy in which this - /// factory participates. - /// - /// - ///

- /// Includes counts of ancestor object factories. - ///

- ///

- /// Objects that are "overridden" (specified in a descendant factory - /// with the same name) are counted only once. - ///

- ///
- /// The object factory. - /// - /// The count of objects including those defined in ancestor factories. - /// - public static int CountObjectsIncludingAncestors(IListableObjectFactory factory) - { - return ObjectNamesIncludingAncestors(factory).Length; - } + /// + /// Count all object definitions in any hierarchy in which this + /// factory participates. + /// + /// + ///

+ /// Includes counts of ancestor object factories. + ///

+ ///

+ /// Objects that are "overridden" (specified in a descendant factory + /// with the same name) are counted only once. + ///

+ ///
+ /// The object factory. + /// + /// The count of objects including those defined in ancestor factories. + /// + public static int CountObjectsIncludingAncestors(IListableObjectFactory factory) + { + return ObjectNamesIncludingAncestors(factory).Length; + } - /// - /// Return all object names in the factory, including ancestor factories. - /// - /// The object factory. - /// The array of object names, or an empty array if none. - public static string[] ObjectNamesIncludingAncestors(IListableObjectFactory factory) - { - ArrayList result = new ArrayList(); - result.AddRange(factory.GetObjectDefinitionNames()); - IListableObjectFactory pof = GetParentFactoryIfAny(factory); - if (pof != null) - { - string[] parentsResult = ObjectNamesIncludingAncestors(pof); - foreach (string s in parentsResult) - { - if (!result.Contains(s)) result.Add(s); - } - } - //return ToArrayOfObjectNames(result); - return (string[]) result.ToArray(typeof (string)); - } + /// + /// Return all object names in the factory, including ancestor factories. + /// + /// The object factory. + /// The array of object names, or an empty array if none. + public static string[] ObjectNamesIncludingAncestors(IListableObjectFactory factory) + { + return ObjectNamesForTypeIncludingAncestors(factory, typeof(object)); + } - /// - /// Get all object names for the given type, including those defined in ancestor - /// factories. - /// - /// - ///

- /// Will return unique names in case of overridden object definitions. - ///

- ///

- /// Does consider objects created by s + ///

+ /// Get all object names for the given type, including those defined in ancestor + /// factories. + /// + /// + ///

+ /// Will return unique names in case of overridden object definitions. + ///

+ ///

+ /// Does consider objects created by s /// if is set to true, /// which means that s will get initialized. - ///

- ///
- /// - /// If this isn't also an - /// , - /// this method will return the same as it's own - /// - /// method. - /// - /// - /// The that objects must match. - /// + ///

+ ///
+ /// + /// If this isn't also an + /// , + /// this method will return the same as it's own + /// + /// method. + /// + /// + /// The that objects must match. + /// /// - /// Whether to include prototype objects too or just singletons - /// (also applies to instances). - /// - /// - /// Whether to include instances - /// too or just normal objects. - /// - /// - /// The array of object names, or an empty array if none. - /// - public static string[] ObjectNamesForTypeIncludingAncestors( - IListableObjectFactory factory, Type type, + /// Whether to include prototype objects too or just singletons + /// (also applies to instances). + /// + /// + /// Whether to include instances + /// too or just normal objects. + /// + /// + /// The array of object names, or an empty array if none. + /// + public static string[] ObjectNamesForTypeIncludingAncestors( + IListableObjectFactory factory, Type type, bool includePrototypes, bool includeFactoryObjects) - { - ArrayList result = new ArrayList(); - result.AddRange(factory.GetObjectNamesForType(type, includePrototypes, includeFactoryObjects)); - IListableObjectFactory pof = GetParentFactoryIfAny(factory); - if (pof != null) - { + { + ArrayList result = new ArrayList(); + result.AddRange(factory.GetObjectNamesForType(type, includePrototypes, includeFactoryObjects)); + IListableObjectFactory pof = GetParentListableObjectFactoryIfAny(factory); + if (pof != null) + { + IHierarchicalObjectFactory hof = (IHierarchicalObjectFactory)factory; string[] parentsResult = ObjectNamesForTypeIncludingAncestors(pof, type, includePrototypes, includeFactoryObjects); - foreach(string s in parentsResult) - { - if (!result.Contains(s)) - { - result.Add(s); - } - } - } - return (string[]) result.ToArray(typeof (string)); - } + foreach (string objectName in parentsResult) + { + if (!result.Contains(objectName) && !hof.ContainsLocalObject(objectName)) + { + result.Add(objectName); + } + } + } + return (string[])result.ToArray(typeof(string)); + } /// /// Get all object names for the given type, including those defined in ancestor @@ -226,266 +215,267 @@ namespace Spring.Objects.Factory { ArrayList result = new ArrayList(); result.AddRange(factory.GetObjectNamesForType(type)); - IListableObjectFactory pof = GetParentFactoryIfAny(factory); + IListableObjectFactory pof = GetParentListableObjectFactoryIfAny(factory); if (pof != null) { + IHierarchicalObjectFactory hof = (IHierarchicalObjectFactory)factory; string[] parentsResult = ObjectNamesForTypeIncludingAncestors(pof, type); - foreach(string s in parentsResult) + foreach (string objectName in parentsResult) { - if (!result.Contains(s)) + if (!result.Contains(objectName) && !hof.ContainsLocalObject(objectName)) { - result.Add(s); + result.Add(objectName); } } } - return (string[]) result.ToArray(typeof (string)); + return (string[])result.ToArray(typeof(string)); } - private static IListableObjectFactory GetParentFactoryIfAny(IListableObjectFactory factory) - { - IHierarchicalObjectFactory hierFactory = factory as IHierarchicalObjectFactory; - if (hierFactory != null) - { - return - hierFactory.ParentObjectFactory as IListableObjectFactory; - } - return null; - } + /// + /// Return all objects of the given type or subtypes, also picking up objects + /// defined in ancestor object factories if the current object factory is an + /// . + /// + /// + ///

+ /// The return list will only contain objects of this type. + /// Useful convenience method when we don't care about object names. + ///

+ ///
+ /// The object factory. + /// The of object to match. + /// + /// Whether to include prototype objects too or just singletons + /// (also applies to instances). + /// + /// + /// Whether to include instances + /// too or just normal objects. + /// + /// + /// If the objects could not be created. + /// + /// + /// The of object instances, or an + /// empty if none. + /// + public static IDictionary ObjectsOfTypeIncludingAncestors( + IListableObjectFactory factory, Type type, + bool includePrototypes, bool includeFactoryObjects) + { + Hashtable result = new Hashtable(); + foreach (DictionaryEntry entry in + factory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects)) + { + result.Add(entry.Key, entry.Value); + } + IListableObjectFactory pof = GetParentListableObjectFactoryIfAny(factory); + if (pof != null) + { + IHierarchicalObjectFactory hof = (IHierarchicalObjectFactory)factory; + IDictionary parentResult = ObjectsOfTypeIncludingAncestors(pof, type, includePrototypes, includeFactoryObjects); + foreach (string objectName in parentResult.Keys) + { + if (!result.ContainsKey(objectName) && !hof.ContainsLocalObject(objectName)) + { + result.Add(objectName, parentResult[objectName]); + } + } + } + return result; + } - /// - /// Return all objects of the given type or subtypes, also picking up objects - /// defined in ancestor object factories if the current object factory is an - /// . - /// - /// - ///

- /// The return list will only contain objects of this type. - /// Useful convenience method when we don't care about object names. - ///

- ///
- /// The object factory. - /// The of object to match. - /// - /// Whether to include prototype objects too or just singletons - /// (also applies to instances). - /// - /// - /// Whether to include instances - /// too or just normal objects. - /// - /// - /// If the objects could not be created. - /// - /// - /// The of object instances, or an - /// empty if none. - /// - public static IDictionary ObjectsOfTypeIncludingAncestors( - IListableObjectFactory factory, Type type, - bool includePrototypes, bool includeFactoryObjects) - { - Hashtable result = new Hashtable(); - foreach (DictionaryEntry entry in - factory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects)) - { - result.Add(entry.Key, entry.Value); - } - IListableObjectFactory pof = GetParentFactoryIfAny(factory); - if (pof != null) - { - IDictionary parentResult - = ObjectsOfTypeIncludingAncestors( - pof, type, includePrototypes, includeFactoryObjects); - foreach (object instance in parentResult.Keys) - { - if (!result.ContainsKey(instance)) - { - result.Add(instance, parentResult[instance]); - } - } - } - return result; - } + /// + /// Return a single object of the given type or subtypes, also picking up objects defined + /// in ancestor object factories if the current object factory is an + /// . + /// + /// + ///

+ /// Useful convenience method when we expect a single object and don't care + /// about the object name. + ///

+ ///
+ /// The object factory. + /// The of object to match. + /// + /// Whether to include prototype objects too or just singletons + /// (also applies to instances). + /// + /// + /// Whether to include instances + /// too or just normal objects. + /// + /// + /// If the object could not be created. + /// + /// + /// If more than one instance of an object was found. + /// + /// + /// A single object of the given type or subtypes. + /// + public static object ObjectOfTypeIncludingAncestors( + IListableObjectFactory factory, Type type, + bool includePrototypes, bool includeFactoryObjects) + { + IDictionary objectsOfType = ObjectsOfTypeIncludingAncestors(factory, type, includePrototypes, includeFactoryObjects); + return GrabTheOnlyObject(objectsOfType, type); + } - /// - /// Return a single object of the given type or subtypes, also picking up objects defined - /// in ancestor object factories if the current object factory is an - /// . - /// - /// - ///

- /// Useful convenience method when we expect a single object and don't care - /// about the object name. - ///

- ///
- /// The object factory. - /// The of object to match. - /// - /// Whether to include prototype objects too or just singletons - /// (also applies to instances). - /// - /// - /// Whether to include instances - /// too or just normal objects. - /// - /// - /// If the object could not be created. - /// - /// - /// If more than one instance of an object was found. - /// - /// - /// A single object of the given type or subtypes. - /// - public static object ObjectOfTypeIncludingAncestors( - IListableObjectFactory factory, Type type, - bool includePrototypes, bool includeFactoryObjects) - { - IDictionary objectsOfType - = ObjectsOfTypeIncludingAncestors( - factory, type, includePrototypes, includeFactoryObjects); - return GrabTheOnlyObject(objectsOfType, type); - } + /// + /// Return a single object of the given type or subtypes, not looking in + /// ancestor factories. + /// + /// + ///

+ /// Useful convenience method when we expect a single object and don't care + /// about the object name. + ///

+ ///
+ /// The object factory. + /// The of object to match. + /// + /// Whether to include prototype objects too or just singletons + /// (also applies to instances). + /// + /// + /// Whether to include instances + /// too or just normal objects. + /// + /// + /// If the object could not be created. + /// + /// + /// If not exactly one instance of an object was found. + /// + /// + /// A single object of the given type or subtypes. + /// + public static object ObjectOfType(IListableObjectFactory factory, Type type, + bool includePrototypes, bool includeFactoryObjects) + { + IDictionary objectsOfType = factory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects); + return GrabTheOnlyObject(objectsOfType, type); + } - private static object GrabTheOnlyObject(IDictionary objectsOfType, Type type) - { - if (objectsOfType.Count == 1) - { - return ObjectUtils.EnumerateFirstElement(objectsOfType.Values); - } - else - { - throw new NoSuchObjectDefinitionException(type, "Expected single object but found " + objectsOfType.Count); - } - } + /// + /// Return a single object of the given type or subtypes, not looking in + /// ancestor factories. + /// + /// + ///

+ /// Useful convenience method when we expect a single object and don't care + /// about the object name. + /// This version of ObjectOfType automatically includes prototypes and + /// instances. + ///

+ ///
+ /// The object factory. + /// The of object to match. + /// + /// If the object could not be created. + /// + /// + /// If not exactly one instance of an object was found. + /// + /// + /// A single object of the given type or subtypes. + /// + public static object ObjectOfType(IListableObjectFactory factory, Type type) + { + return ObjectOfType(factory, type, true, true); + } - /// - /// Return a single object of the given type or subtypes, not looking in - /// ancestor factories. - /// - /// - ///

- /// Useful convenience method when we expect a single object and don't care - /// about the object name. - ///

- ///
- /// The object factory. - /// The of object to match. - /// - /// Whether to include prototype objects too or just singletons - /// (also applies to instances). - /// - /// - /// Whether to include instances - /// too or just normal objects. - /// - /// - /// If the object could not be created. - /// - /// - /// If not exactly one instance of an object was found. - /// - /// - /// A single object of the given type or subtypes. - /// - public static object ObjectOfType(IListableObjectFactory factory, Type type, - bool includePrototypes, bool includeFactoryObjects) - { - IDictionary objectsOfType - = factory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects); - return GrabTheOnlyObject(objectsOfType, type); - } - - /// - /// Return a single object of the given type or subtypes, not looking in - /// ancestor factories. - /// - /// - ///

- /// Useful convenience method when we expect a single object and don't care - /// about the object name. - /// This version of ObjectOfType automatically includes prototypes and - /// instances. - ///

- ///
- /// The object factory. - /// The of object to match. - /// - /// If the object could not be created. - /// - /// - /// If not exactly one instance of an object was found. - /// - /// - /// A single object of the given type or subtypes. - /// - public static object ObjectOfType(IListableObjectFactory factory, Type type) - { - return ObjectOfType(factory, type, true, true); - } - - /// - /// Return the object name, stripping out the factory dereference prefix if necessary. - /// - /// The name of the object. - /// The object name sans any factory dereference prefix. - public static string TransformedObjectName(string name) - { - AssertUtils.ArgumentNotNull(name, "name", "Object name must not be null."); - if (!ObjectFactoryUtils.IsFactoryDereference(name)) - { + /// + /// Return the object name, stripping out the factory dereference prefix if necessary. + /// + /// The name of the object. + /// The object name sans any factory dereference prefix. + public static string TransformedObjectName(string name) + { + AssertUtils.ArgumentNotNull(name, "name", "Object name must not be null."); + if (!ObjectFactoryUtils.IsFactoryDereference(name)) + { return name; - } + } - string objectName = name.Substring(ObjectFactoryUtils.FactoryObjectPrefix.Length); - return objectName; - } + string objectName = name.Substring(ObjectFactoryUtils.FactoryObjectPrefix.Length); + return objectName; + } - /// - /// Given an (object) name, builds a corresponding factory object name such that - /// the return value can be used as a lookup name for a factory object. - /// - /// - /// The name to be used to build the resulting factory object name. - /// - /// - /// The transformed into its factory object name - /// equivalent. - /// - /// - /// - public static string BuildFactoryObjectName(string objectName) - { - return ObjectFactoryUtils.FactoryObjectPrefix + objectName; - } + /// + /// Given an (object) name, builds a corresponding factory object name such that + /// the return value can be used as a lookup name for a factory object. + /// + /// + /// The name to be used to build the resulting factory object name. + /// + /// + /// The transformed into its factory object name + /// equivalent. + /// + /// + /// + public static string BuildFactoryObjectName(string objectName) + { + return ObjectFactoryUtils.FactoryObjectPrefix + objectName; + } - /// - /// Is the supplied a factory dereference? - /// - /// - ///

- /// That is, does the supplied begin with - /// the - /// ? - ///

- ///
- /// The name to check. - /// - /// if the supplied is a - /// factory dereference; if not, or the - /// aupplied is or - /// consists solely of the - /// - /// value. - /// - /// - public static bool IsFactoryDereference(string name) - { - return name != null - && name.Length > ObjectFactoryUtils.FactoryObjectPrefix.Length + /// + /// Is the supplied a factory dereference? + /// + /// + ///

+ /// That is, does the supplied begin with + /// the + /// ? + ///

+ ///
+ /// The name to check. + /// + /// if the supplied is a + /// factory dereference; if not, or the + /// aupplied is or + /// consists solely of the + /// + /// value. + /// + /// + public static bool IsFactoryDereference(string name) + { + return name != null + && name.Length > ObjectFactoryUtils.FactoryObjectPrefix.Length && name[0] == ObjectFactoryUtils.FactoryObjectPrefix[0] - && name.StartsWith(ObjectFactoryUtils.FactoryObjectPrefix) + && name.StartsWith(ObjectFactoryUtils.FactoryObjectPrefix) ; - } - } + } + + #region Private Utility Methods + + private static IListableObjectFactory GetParentListableObjectFactoryIfAny(IListableObjectFactory factory) + { + IHierarchicalObjectFactory hierFactory = factory as IHierarchicalObjectFactory; + if (hierFactory != null) + { + return + hierFactory.ParentObjectFactory as IListableObjectFactory; + } + return null; + } + + private static object GrabTheOnlyObject(IDictionary objectsOfType, Type type) + { + if (objectsOfType.Count == 1) + { + return ObjectUtils.EnumerateFirstElement(objectsOfType.Values); + } + else + { + throw new NoSuchObjectDefinitionException(type, "Expected single object but found " + objectsOfType.Count); + } + } + + #endregion + } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs index 883d6706..45413425 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs @@ -384,7 +384,7 @@ namespace Spring.Objects.Factory.Support return objectType as string; } } - set { objectType = value; } + set { objectType = StringUtils.GetTextOrNull(value); } } /// @@ -394,7 +394,7 @@ namespace Spring.Objects.Factory.Support public string ResourceDescription { get { return resourceDescription; } - set { resourceDescription = value; } + set { resourceDescription = StringUtils.GetTextOrNull(value); } } /// @@ -515,7 +515,7 @@ namespace Spring.Objects.Factory.Support public string InitMethodName { get { return initMethodName; } - set { initMethodName = value; } + set { initMethodName = StringUtils.GetTextOrNull(value); } } /// @@ -530,7 +530,7 @@ namespace Spring.Objects.Factory.Support public string DestroyMethodName { get { return destroyMethodName; } - set { destroyMethodName = value; } + set { destroyMethodName = StringUtils.GetTextOrNull(value); } } /// @@ -547,7 +547,7 @@ namespace Spring.Objects.Factory.Support public string FactoryMethodName { get { return factoryMethodName; } - set { factoryMethodName = value; } + set { factoryMethodName = StringUtils.GetTextOrNull(value); } } /// @@ -556,7 +556,7 @@ namespace Spring.Objects.Factory.Support public string FactoryObjectName { get { return factoryObjectName; } - set { factoryObjectName = value; } + set { factoryObjectName = StringUtils.GetTextOrNull(value); } } /// @@ -759,7 +759,7 @@ namespace Spring.Objects.Factory.Support private MutablePropertyValues propertyValues = new MutablePropertyValues(); private EventValues eventHandlerValues = new EventValues(); private MethodOverrides methodOverrides = new MethodOverrides(); - private string resourceDescription = string.Empty; + private string resourceDescription = null; private bool isSingleton = true; private bool isPrototype = false; private bool isLazyInit = false; @@ -769,10 +769,10 @@ namespace Spring.Objects.Factory.Support private DependencyCheckingMode dependencyCheck = DependencyCheckingMode.None; private string[] dependsOn; private bool autowireCandidate = true; - private string initMethodName = string.Empty; - private string destroyMethodName = string.Empty; - private string factoryMethodName = string.Empty; - private string factoryObjectName = string.Empty; + private string initMethodName = null; + private string destroyMethodName = null; + private string factoryMethodName = null; + private string factoryObjectName = null; #endregion } diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs index af4c3194..50ffab07 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs @@ -78,7 +78,8 @@ namespace Spring.Objects.Factory.Support /// Creates a new instance of the /// class. /// - public DefaultListableObjectFactory() : this(true, null) + public DefaultListableObjectFactory() + : this(true, null) { } @@ -87,7 +88,8 @@ namespace Spring.Objects.Factory.Support /// class. /// /// Flag specifying whether to make this object factory case sensitive or not. - public DefaultListableObjectFactory(bool caseSensitive) : this(caseSensitive, null) + public DefaultListableObjectFactory(bool caseSensitive) + : this(caseSensitive, null) { } @@ -164,7 +166,7 @@ namespace Spring.Objects.Factory.Support } set { - AssertUtils.ArgumentNotNull(value, "AutowireCandidateResolver"); + AssertUtils.ArgumentNotNull(value, "AutowireCandidateResolver"); autowireCandidateResolver = value; } } @@ -250,7 +252,7 @@ namespace Spring.Objects.Factory.Support } } } - return (string[]) dependingObjectNames.ToArray(typeof(string)); + return (string[])dependingObjectNames.ToArray(typeof(string)); } /// @@ -283,22 +285,22 @@ namespace Spring.Objects.Factory.Support RootObjectDefinition rod = GetMergedObjectDefinition(name, false); return (rod.HasObjectType && checkedType.IsAssignableFrom(rod.ObjectType)); } -/* - /// - /// Merges the object definitions. - /// - /// Object definition name. - /// The parent definition. - /// The child definition. - /// Merged object definition. - protected override RootObjectDefinition MergeObjectDefinitions(string name, IObjectDefinition parentDefinition, - IObjectDefinition childDefinition) - { - RootObjectDefinition rootDefinition = base.MergeObjectDefinitions(name, parentDefinition, childDefinition); - RegisterObjectDefinition(name, rootDefinition); - return rootDefinition; - } -*/ + /* + /// + /// Merges the object definitions. + /// + /// Object definition name. + /// The parent definition. + /// The child definition. + /// Merged object definition. + protected override RootObjectDefinition MergeObjectDefinitions(string name, IObjectDefinition parentDefinition, + IObjectDefinition childDefinition) + { + RootObjectDefinition rootDefinition = base.MergeObjectDefinitions(name, parentDefinition, childDefinition); + RegisterObjectDefinition(name, rootDefinition); + return rootDefinition; + } + */ #endregion #region Fields @@ -332,7 +334,7 @@ namespace Spring.Objects.Factory.Support /// /// IDictionary from dependency type to corresponding autowired value /// - private readonly IDictionary resolvableDependencies = new Hashtable(); + private readonly IDictionary resolvableDependencies = new Hashtable(); #endregion @@ -387,7 +389,7 @@ namespace Spring.Objects.Factory.Support { try { - ((AbstractObjectDefinition) objectDefinition).Validate(); + ((AbstractObjectDefinition)objectDefinition).Validate(); } catch (ObjectDefinitionValidationException ex) { @@ -458,7 +460,7 @@ namespace Spring.Objects.Factory.Support int definitionCount = objectDefinitionNames.Count; for (int i = 0; i < definitionCount; i++) { - string name = (string) objectDefinitionNames[i]; + string name = (string)objectDefinitionNames[i]; if (!ContainsSingleton(name) && ContainsObjectDefinition(name)) { RootObjectDefinition definition @@ -471,7 +473,7 @@ namespace Spring.Objects.Factory.Support if (objectType != null && typeof(IFactoryObject).IsAssignableFrom(definition.ObjectType)) { - IFactoryObject factoryObject = (IFactoryObject) GetObject( + IFactoryObject factoryObject = (IFactoryObject)GetObject( ObjectFactoryUtils. BuildFactoryObjectName(name)); if (factoryObject.IsSingleton) @@ -583,7 +585,7 @@ namespace Spring.Objects.Factory.Support } name = TransformedObjectName(name); - IObjectDefinition definition = (IObjectDefinition) objectDefinitionMap[name]; + IObjectDefinition definition = (IObjectDefinition)objectDefinitionMap[name]; if (definition == null) { if (!includeAncestors || ParentObjectFactory == null) @@ -593,10 +595,10 @@ namespace Spring.Objects.Factory.Support else if (ParentObjectFactory is AbstractObjectFactory) { definition = - ((AbstractObjectFactory) ParentObjectFactory).GetObjectDefinition(name, includeAncestors); + ((AbstractObjectFactory)ParentObjectFactory).GetObjectDefinition(name, includeAncestors); } } - return definition; + return definition; } #endregion @@ -613,7 +615,7 @@ namespace Spring.Objects.Factory.Support /// public string[] GetObjectDefinitionNames() { - return (string[]) ((ArrayList) objectDefinitionNames).ToArray(typeof(string)); + return (string[])((ArrayList)objectDefinitionNames).ToArray(typeof(string)); } /// @@ -639,7 +641,7 @@ namespace Spring.Objects.Factory.Support matches.Add(name); } } - return (string[]) matches.ToArray(typeof(string)); + return (string[])matches.ToArray(typeof(string)); } /// @@ -685,7 +687,7 @@ namespace Spring.Objects.Factory.Support Type type, bool includePrototypes, bool includeFactoryObjects) { IList objectNames = DoGetObjectNamesForType(type, includePrototypes, includeFactoryObjects); - return (string[]) ArrayList.Adapter(objectNames).ToArray(typeof(string)); + return (string[])ArrayList.Adapter(objectNames).ToArray(typeof(string)); } /// @@ -772,60 +774,102 @@ namespace Spring.Objects.Factory.Support return result; } - // TODO: (ee) What's this method for? It's never used. -/* - protected IList DoGetObjectNamesForTypeNew(Type type, bool includePrototypes, bool includeFactoryObjects) + /// + /// Return the object instances that match the given object + /// (including subclasses). + /// + /// + /// 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. + /// + /// + /// An of the matching objects, + /// containing the object names as keys and the corresponding object instances + /// as values. + /// + /// + /// If any of the objects could not be created. + /// + /// + protected IList DoGetObjectNamesForType(Type type, bool includeNonSingletons, bool allowEagerInit) { IList result = new ArrayList(); string[] objectNames = GetObjectDefinitionNames(); - foreach (string objectNam in objectNames) + foreach (string s in objectNames) { - string objectName = objectNam; + string objectName = s; if (!IsAlias(objectName)) { - RootObjectDefinition mod = GetMergedObjectDefinition(objectName, false); - // Only check object definition if it is complete - if (!mod.IsAbstract && - (mod.HasObjectType || !mod.IsLazyInit)) - { - // In case of FactoryObject, match object created by FactoryObject - } try { - bool isFactoryObject = IsObjectTypeMatch(objectName, mod, typeof(IFactoryObject)); - bool matchFound = (includePrototypes || mod.IsSingleton) && IsTypeMatch(objectName, type); - if (!matchFound && isFactoryObject) + RootObjectDefinition mod = GetMergedObjectDefinition(objectName, false); + // Only check object definition if it is complete + if (!mod.IsAbstract && + (allowEagerInit || (mod.HasObjectType || !mod.IsLazyInit /*|| this.AllowEagerTypeLoading*/ ) && + !RequiresEagerInitForType(mod.FactoryObjectName) )) { - objectName = ObjectFactoryUtils.BuildFactoryObjectName(objectName); - matchFound = (includePrototypes || mod.IsSingleton) && IsTypeMatch(objectName, type); - } - if (matchFound) - { - result.Add(objectName); + bool isFactoryObject = IsFactoryObject(objectName, mod); + bool matchFound = + (allowEagerInit || !isFactoryObject || ContainsSingleton(objectName)) && + (includeNonSingletons || IsSingleton(objectName)) && IsTypeMatch(objectName, type); + if (!matchFound && isFactoryObject) + { + // in case of a FactoryObject, try to match FactoryObject instance itself next + objectName = ObjectFactoryUtils.BuildFactoryObjectName(objectName); + matchFound = (includeNonSingletons || mod.IsSingleton) && IsTypeMatch(objectName, type); + } + if (matchFound) + { + result.Add(objectName); + } } } catch (CannotLoadObjectTypeException ex) { + if (allowEagerInit) + { + throw; + } // Probably contains a placeholder; lets ignore it for type matching purposes. if (log.IsDebugEnabled) { log.Debug("Ignoring object class loading failure for object '" + objectName + "'", ex); } } + catch(ObjectDefinitionStoreException ex) + { + if (allowEagerInit) + { + throw; + } + // Probably contains a placeholder; lets ignore it for type matching purposes. + if (log.IsDebugEnabled) + { + log.Debug("Ignoring unresolvable metadata in object definition '" + objectName + "'", ex); + } + } } } + // check singletons too, to catch manually registered singletons... string[] singletonNames = GetSingletonNames(); - foreach (string objectNam in singletonNames) + foreach (string s in singletonNames) { - string objectName = objectNam; + string objectName = s; // only check if manually registered... if (!ContainsObjectDefinition(objectName)) { // in the case of an IFactoryObject, match the object created by the IFactoryObject... if (IsFactoryObject(objectName)) { - if ((includePrototypes || IsSingleton(objectName)) && IsTypeMatch(objectName, type)) + if ((includeNonSingletons || IsSingleton(objectName)) && IsTypeMatch(objectName, type)) { result.Add(objectName); continue; @@ -840,43 +884,42 @@ namespace Spring.Objects.Factory.Support } return result; } -*/ /// - /// Return the object instances that match the given object - /// (including subclasses). + /// Check whether the specified bean would need to be eagerly initialized + /// in order to determine its type. /// - /// - /// 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. - /// - /// - /// An of the matching objects, - /// containing the object names as keys and the corresponding object instances - /// as values. - /// - /// - /// If any of the objects could not be created. - /// - /// - protected IList DoGetObjectNamesForType( - Type type, bool includePrototypes, bool includeFactoryObjects) + /// a factory-bean reference that the bean definition defines a factory method for + /// whether eager initialization is necessary + private bool RequiresEagerInitForType(String factoryObjectName) + { + return (factoryObjectName != null && IsFactoryObject(factoryObjectName) && !ContainsSingleton(factoryObjectName)); + } + + /// + /// Check whether the given bean is defined as a . + /// + /// the name of the object + /// the corresponding object definition + protected bool IsFactoryObject(String objectName, RootObjectDefinition rod) + { + Type objectType = PredictObjectType(objectName, rod); + return (objectType != null && typeof(IFactoryObject).IsAssignableFrom(objectType)); + } + + private IList DoGetObjectNamesForTypeOld(Type type, bool includePrototypes, bool includeFactoryObjects) { bool isFactoryType = (type != null && typeof(IFactoryObject).IsAssignableFrom(type)); IList result = new ArrayList(); - if (type != null) + // if (type != null) { string[] objectNames = GetObjectDefinitionNames(); foreach (string objectName in objectNames) { - RootObjectDefinition rod = GetMergedObjectDefinition(objectName, false); + // only check object definition if it is not an alias for another object + if (IsAlias(objectName)) continue; + + RootObjectDefinition rod = GetMergedObjectDefinition(objectName, false); // TODO: check merge ancestors w/ Java // only check complete object definitions... if (!rod.IsAbstract && rod.HasObjectType) { @@ -890,7 +933,7 @@ namespace Spring.Objects.Factory.Support result.Add(objectName); } } - // in the case of an IFactoryObject, match the object created by the IFactoryObject... + // in the case of an IFactoryObject, match the object created by the IFactoryObject... else if (typeof(IFactoryObject).IsAssignableFrom(rod.ObjectType) && !isFactoryType) { if (includeFactoryObjects && (includePrototypes || IsSingleton(objectName)) && @@ -990,30 +1033,32 @@ namespace Spring.Objects.Factory.Support } } return TypeConversionUtils.ConvertValueIfNecessary(type, matchingObjects.Values, null); - } else if (typeof(ICollection).IsAssignableFrom(type) && type.IsInterface) + } + else if (typeof(ICollection).IsAssignableFrom(type) && type.IsInterface) { //TODO - handle generic types. return null; - } else + } + else { IDictionary matchingObjects = FindAutowireCandidates(objectName, type, descriptor); if (matchingObjects.Count == 0) { if (descriptor.Required) { - string methodType = (descriptor.MethodParameter.ConstructorInfo != null) ? "constructor" : "method"; - throw new NoSuchObjectDefinitionException(type, - "Unsatisfied dependency of type [" + type + "]: expected at least 1 matching object to wire the [" - + descriptor.MethodParameter.ParameterName() + "] parameter on the " + methodType + " of object [" + objectName + "]"); + string methodType = (descriptor.MethodParameter.ConstructorInfo != null) ? "constructor" : "method"; + throw new NoSuchObjectDefinitionException(type, + "Unsatisfied dependency of type [" + type + "]: expected at least 1 matching object to wire the [" + + descriptor.MethodParameter.ParameterName() + "] parameter on the " + methodType + " of object [" + objectName + "]"); } return null; } if (matchingObjects.Count > 1) { - - throw new NoSuchObjectDefinitionException(type, - "expected single matching object but found " + matchingObjects.Count + ": " + matchingObjects); + + throw new NoSuchObjectDefinitionException(type, + "expected single matching object but found " + matchingObjects.Count + ": " + matchingObjects); } DictionaryEntry entry = (DictionaryEntry)ObjectUtils.EnumerateFirstElement(matchingObjects); if (autowiredObjectNames != null) @@ -1049,7 +1094,7 @@ namespace Spring.Objects.Factory.Support #endif foreach (DictionaryEntry entry in resolvableDependencies) { - Type autoWiringType = (Type) entry.Key; + Type autoWiringType = (Type)entry.Key; if (autoWiringType.IsAssignableFrom(requiredType)) { object autowiringValue = this.resolvableDependencies[autoWiringType]; @@ -1058,7 +1103,7 @@ namespace Spring.Objects.Factory.Support result.Add(ObjectUtils.IdentityToString(autowiringValue), autowiringValue); break; } - } + } } for (int i = 0; i < candidateNames.Length; i++) { @@ -1086,7 +1131,7 @@ namespace Spring.Objects.Factory.Support { //Consider FactoryObjects as autowiring candidates. bool isFactoryObject = (descriptor != null && descriptor.DependencyType != null && - typeof (IFactoryObject).IsAssignableFrom(descriptor.DependencyType)); + typeof(IFactoryObject).IsAssignableFrom(descriptor.DependencyType)); if (isFactoryObject) { objectName = ObjectFactoryUtils.TransformedObjectName(objectName); @@ -1102,7 +1147,7 @@ namespace Spring.Objects.Factory.Support { // No object definition found in this factory -> delegate to parent return - ((IConfigurableListableObjectFactory) ParentObjectFactory).IsAutowireCandidate(objectName, descriptor); + ((IConfigurableListableObjectFactory)ParentObjectFactory).IsAutowireCandidate(objectName, descriptor); } } return IsAutowireCandidate(objectName, GetMergedObjectDefinition(objectName, true), descriptor); diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionReaderUtils.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionReaderUtils.cs index 68a297af..8140318b 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionReaderUtils.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionReaderUtils.cs @@ -152,11 +152,16 @@ namespace Spring.Objects.Factory.Support } if (StringUtils.IsNullOrEmpty(generatedObjectName)) { - throw new ObjectDefinitionStoreException( - objectDefinition.ResourceDescription, String.Empty, - "Unnamed object definition specifies neither 'Type' nor 'Parent' " + - "nor 'FactoryObject' property values so a unique name cannot be generated."); + if (!isInnerObject) + { + throw new ObjectDefinitionStoreException( + objectDefinition.ResourceDescription, String.Empty, + "Unnamed object definition specifies neither 'Type' nor 'Parent' " + + "nor 'FactoryObject' property values so a unique name cannot be generated."); + } + generatedObjectName = "$nested"; } + String id = generatedObjectName; if (isInnerObject) { diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/AbstractObjectDefinitionParser.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/AbstractObjectDefinitionParser.cs index e40dad6f..909d3aa2 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/AbstractObjectDefinitionParser.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/AbstractObjectDefinitionParser.cs @@ -160,8 +160,8 @@ namespace Spring.Objects.Factory.Xml if (ShouldGenerateId) { return parserContext.ReaderContext.GenerateObjectName(definition); } - else { - string id = element.GetAttribute(ID_ATTRIBUTE); + else { + string id = GetAttributeValue(element, ID_ATTRIBUTE); if (!StringUtils.HasText(id) && ShouldGenerateIdAsFallback) { id = parserContext.ReaderContext.GenerateObjectName(definition); } @@ -189,7 +189,40 @@ namespace Spring.Objects.Factory.Xml protected virtual void RegisterObjectDefinition(ObjectDefinitionHolder definition, IObjectDefinitionRegistry registry) { ObjectDefinitionReaderUtils.RegisterObjectDefinition(definition, registry); - } + } + + /// + /// Returns the value of the element's attribute or null, if the attribute is not specified. + /// + /// + /// This is a helper for bypassing the behavior of + /// to return if the attribute does not exist. + /// + protected static string GetAttributeValue(XmlElement element, string attributeName) + { + if (element.HasAttribute(attributeName)) + { + return element.GetAttribute(attributeName); + } + return null; + } + + /// + /// Returns the value of the element's attribute or , + /// if the attribute is not specified. + /// + /// + /// This is a helper for bypassing the behavior of + /// to return if the attribute does not exist. + /// + protected static string GetAttributeValue(XmlElement element, string attributeName, string defaultValue) + { + if (element.HasAttribute(attributeName)) + { + return element.GetAttribute(attributeName); + } + return defaultValue; + } #endregion diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs index d98b9637..cf61115b 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs @@ -99,7 +99,7 @@ namespace Spring.Objects.Factory.Xml #endregion - ddd.LazyInit = root.GetAttribute(ObjectDefinitionConstants.DefaultLazyInitAttribute); + ddd.LazyInit = GetAttributeValue(root, ObjectDefinitionConstants.DefaultLazyInitAttribute); #region Instrumentation @@ -111,9 +111,9 @@ namespace Spring.Objects.Factory.Xml ddd.LazyInit)); } - #endregion - - ddd.DependencyCheck = root.GetAttribute(ObjectDefinitionConstants.DefaultDependencyCheckAttribute); + #endregion + + ddd.DependencyCheck = GetAttributeValue(root, ObjectDefinitionConstants.DefaultDependencyCheckAttribute); #region Instrumentation @@ -125,9 +125,9 @@ namespace Spring.Objects.Factory.Xml ddd.DependencyCheck)); } - #endregion - - ddd.Autowire = root.GetAttribute(ObjectDefinitionConstants.DefaultAutowireAttribute); + #endregion + + ddd.Autowire = GetAttributeValue(root, ObjectDefinitionConstants.DefaultAutowireAttribute); #region Instrumentation @@ -203,8 +203,39 @@ namespace Spring.Objects.Factory.Xml public ObjectDefinitionBuilder CreateRootObjectDefinitionBuilder(Type objectType) { return ObjectDefinitionBuilder.RootObjectDefinition(this.readerContext.ObjectDefinitionFactory, objectType); + } + + /// + /// Returns the value of the element's attribute or null, if the attribute is not specified. + /// + /// + /// This is a helper for bypassing the behavior of + /// to return if the attribute does not exist. + /// + public string GetAttributeValue(XmlElement element, string attributeName) + { + if (element.HasAttribute(attributeName)) + { + return element.GetAttribute(attributeName); + } + return null; + } + + /// + /// Returns the value of the element's attribute or , + /// if the attribute is not specified. + /// + /// + /// This is a helper for bypassing the behavior of + /// to return if the attribute does not exist. + /// + public string GetAttributeValue(XmlElement element, string attributeName, string defaultValue) + { + if (element.HasAttribute(attributeName)) + { + return element.GetAttribute(attributeName); + } + return defaultValue; } - - } } diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs index 33fb19eb..ba046ed3 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs @@ -160,13 +160,10 @@ namespace Spring.Objects.Factory.Xml private void ParseAlias(XmlElement aliasElement, IObjectDefinitionRegistry registry) { - string name = aliasElement.GetAttribute(ObjectDefinitionConstants.NameAttribute); - string alias = aliasElement.GetAttribute(ObjectDefinitionConstants.AliasAttribute); + string name = GetAttributeValue(aliasElement, ObjectDefinitionConstants.NameAttribute); + string alias = GetAttributeValue(aliasElement, ObjectDefinitionConstants.AliasAttribute); registry.RegisterAlias(name, alias); } - - - /// /// Loads external XML object definitions from the resource described by the supplied @@ -179,7 +176,7 @@ namespace Spring.Objects.Factory.Xml /// protected virtual void ImportObjectDefinitionResource(XmlElement resource, ParserContext parserContext) { - string location = resource.GetAttribute(ObjectDefinitionConstants.ImportResourceAttribute); + string location = GetAttributeValue(resource, ObjectDefinitionConstants.ImportResourceAttribute); try { #region Instrumentation @@ -223,8 +220,8 @@ namespace Spring.Objects.Factory.Xml // get an appropriate IEventHandlerValue instance based upon the // attribute values of the listener element... IEventHandlerValue myHandler = ObjectDefinitionReaderUtils.CreateEventHandlerValue( - element.GetAttribute(ObjectDefinitionConstants.ListenerMethodAttribute), - element.GetAttribute(ObjectDefinitionConstants.ListenerEventAttribute)); + GetAttributeValue(element, ObjectDefinitionConstants.ListenerMethodAttribute), + GetAttributeValue(element, ObjectDefinitionConstants.ListenerEventAttribute)); // and then get the source of the event (another managed object instance // or a Type reference (i.e. a static event exposed on a class)... @@ -333,8 +330,8 @@ namespace Spring.Objects.Factory.Xml /// protected ObjectDefinitionHolder ParseObjectDefinitionElement(XmlElement element, ParserContext parserContext, bool nestedDefinition) { - string id = element.GetAttribute(ObjectDefinitionConstants.IdAttribute); - string nameAttr = element.GetAttribute(ObjectDefinitionConstants.NameAttribute); + string id = GetAttributeValue(element, ObjectDefinitionConstants.IdAttribute); + string nameAttr = GetAttributeValue(element, ObjectDefinitionConstants.NameAttribute); ArrayList aliases = new ArrayList(); if (StringUtils.HasText(nameAttr)) { @@ -445,15 +442,17 @@ namespace Spring.Objects.Factory.Xml { if (element.HasAttribute(ObjectDefinitionConstants.TypeAttribute)) { - typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute); + typeName = GetAttributeValue(element, ObjectDefinitionConstants.TypeAttribute); if (StringUtils.IsNullOrEmpty(typeName)) { throw new ObjectDefinitionStoreException( parserContext.ReaderContext.Resource, id, - "The 'type' attribute does not need to be present, but if it is it must not be empty: got '" + typeName + "'."); + "The 'type' attribute does not need to be present, but if it is it must not be empty: got '" + + typeName + "'."); } } - string parent = element.GetAttribute(ObjectDefinitionConstants.ParentAttribute); + + string parent = GetAttributeValue(element, ObjectDefinitionConstants.ParentAttribute); AbstractObjectDefinition od @@ -478,38 +477,38 @@ namespace Spring.Objects.Factory.Xml od.EventHandlerValues = events; if (element.HasAttribute(ObjectDefinitionConstants.DependsOnAttribute)) { - string dependsOn = element.GetAttribute(ObjectDefinitionConstants.DependsOnAttribute); + string dependsOn = GetAttributeValue(element, ObjectDefinitionConstants.DependsOnAttribute); od.DependsOn = GetObjectNames(dependsOn); } - od.FactoryMethodName = element.GetAttribute(ObjectDefinitionConstants.FactoryMethodAttribute); - od.FactoryObjectName = element.GetAttribute(ObjectDefinitionConstants.FactoryObjectAttribute); - string dependencyCheck = element.GetAttribute(ObjectDefinitionConstants.DependencyCheckAttribute); + od.FactoryMethodName = GetAttributeValue(element, ObjectDefinitionConstants.FactoryMethodAttribute); + od.FactoryObjectName = GetAttributeValue(element, ObjectDefinitionConstants.FactoryObjectAttribute); + string dependencyCheck = GetAttributeValue(element, ObjectDefinitionConstants.DependencyCheckAttribute); if (ObjectDefinitionConstants.DefaultValue.Equals(dependencyCheck)) { dependencyCheck = parserContext.ParserHelper.Defaults.DependencyCheck; } od.DependencyCheck = GetDependencyCheck(dependencyCheck); - string autowire = element.GetAttribute(ObjectDefinitionConstants.AutowireAttribute); + string autowire = GetAttributeValue(element, ObjectDefinitionConstants.AutowireAttribute); if (ObjectDefinitionConstants.DefaultValue.Equals(autowire)) { autowire = parserContext.ParserHelper.Defaults.Autowire; } od.AutowireMode = GetAutowireMode(autowire); - string initMethodName = element.GetAttribute(ObjectDefinitionConstants.InitMethodAttribute); + string initMethodName = GetAttributeValue(element, ObjectDefinitionConstants.InitMethodAttribute); if (StringUtils.HasText(initMethodName)) { od.InitMethodName = initMethodName; } - string destroyMethodName = element.GetAttribute(ObjectDefinitionConstants.DestroyMethodAttribute); + string destroyMethodName = GetAttributeValue(element, ObjectDefinitionConstants.DestroyMethodAttribute); if (StringUtils.HasText(destroyMethodName)) { od.DestroyMethodName = destroyMethodName; } if (element.HasAttribute(ObjectDefinitionConstants.SingletonAttribute)) { - od.IsSingleton = IsTrueStringValue(element.GetAttribute(ObjectDefinitionConstants.SingletonAttribute).ToLower(CultureInfo.CurrentCulture)); + od.IsSingleton = IsTrueStringValue(GetAttributeValue(element, ObjectDefinitionConstants.SingletonAttribute, string.Empty).ToLower(CultureInfo.CurrentCulture)); } - string lazyInit = element.GetAttribute(ObjectDefinitionConstants.LazyInitAttribute); + string lazyInit = GetAttributeValue(element, ObjectDefinitionConstants.LazyInitAttribute); if (ObjectDefinitionConstants.DefaultValue.Equals(lazyInit) && od.IsSingleton) { // just apply default to singletons, as lazy-init has no meaning for prototypes... @@ -529,7 +528,7 @@ namespace Spring.Objects.Factory.Xml } od.ResourceDescription = resourceDescription; - string isAbstract = element.GetAttribute(ObjectDefinitionConstants.AbstractAttribute); + string isAbstract = GetAttributeValue(element, ObjectDefinitionConstants.AbstractAttribute); if (StringUtils.HasText(isAbstract)) { od.IsAbstract = IsTrueStringValue(isAbstract); @@ -577,8 +576,8 @@ namespace Spring.Objects.Factory.Xml protected void ParseLookupMethodElement( string name, MethodOverrides overrides, XmlElement element, ParserContext parserContext) { - string methodName = element.GetAttribute(ObjectDefinitionConstants.LookupMethodNameAttribute); - string targetObjectName = element.GetAttribute(ObjectDefinitionConstants.LookupMethodObjectNameAttribute); + string methodName = GetAttributeValue(element, ObjectDefinitionConstants.LookupMethodNameAttribute); + string targetObjectName = GetAttributeValue(element, ObjectDefinitionConstants.LookupMethodObjectNameAttribute); if (StringUtils.IsNullOrEmpty(methodName)) { throw new ObjectDefinitionStoreException( @@ -602,8 +601,8 @@ namespace Spring.Objects.Factory.Xml protected void ParseReplacedMethodElement( string name, MethodOverrides overrides, XmlElement element, ParserContext parserContext) { - string methodName = element.GetAttribute(ObjectDefinitionConstants.ReplacedMethodNameAttribute); - string targetReplacerObjectName = element.GetAttribute(ObjectDefinitionConstants.ReplacedMethodReplacerNameAttribute); + string methodName = GetAttributeValue(element, ObjectDefinitionConstants.ReplacedMethodNameAttribute); + string targetReplacerObjectName = GetAttributeValue(element, ObjectDefinitionConstants.ReplacedMethodReplacerNameAttribute); if (StringUtils.IsNullOrEmpty(methodName)) { throw new ObjectDefinitionStoreException( @@ -622,7 +621,7 @@ namespace Spring.Objects.Factory.Xml foreach (XmlNode node in this.SelectNodes(element, ObjectDefinitionConstants.ReplacedMethodArgumentTypeElement)) { XmlElement argElement = (XmlElement) node; - string match = argElement.GetAttribute(ObjectDefinitionConstants.ReplacedMethodArgumentTypeMatchAttribute); + string match = GetAttributeValue(argElement, ObjectDefinitionConstants.ReplacedMethodArgumentTypeMatchAttribute); if (StringUtils.IsNullOrEmpty(match)) { throw new ObjectDefinitionStoreException( @@ -708,9 +707,9 @@ namespace Spring.Objects.Factory.Xml string name, ConstructorArgumentValues arguments, XmlElement element, ParserContext parserContext) { object val = ParsePropertyValue(element, name, parserContext); - string indexAttr = element.GetAttribute(ObjectDefinitionConstants.IndexAttribute); - string typeAttr = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute); - string nameAttr = element.GetAttribute(ObjectDefinitionConstants.ArgumentNameAttribute); + string indexAttr = GetAttributeValue(element, ObjectDefinitionConstants.IndexAttribute); + string typeAttr = GetAttributeValue(element, ObjectDefinitionConstants.TypeAttribute); + string nameAttr = GetAttributeValue(element, ObjectDefinitionConstants.ArgumentNameAttribute); // only one of the 'index' or 'name' attributes can be present if (StringUtils.HasText(indexAttr) @@ -789,7 +788,7 @@ namespace Spring.Objects.Factory.Xml protected void ParsePropertyElement( string name, MutablePropertyValues properties, XmlElement element, ParserContext parserContext) { - string propertyName = element.GetAttribute(ObjectDefinitionConstants.NameAttribute); + string propertyName = GetAttributeValue(element, ObjectDefinitionConstants.NameAttribute); if (StringUtils.IsNullOrEmpty(propertyName)) { throw new ObjectDefinitionStoreException( @@ -955,11 +954,11 @@ namespace Spring.Objects.Factory.Xml private static object ParseIdReference(XmlElement element, ObjectDefinitionParserHelper parserHelper, string name) { // a generic reference to any name of any object - string objectRef = element.GetAttribute(ObjectDefinitionConstants.ObjectRefAttribute); + string objectRef = GetAttributeValue(element, ObjectDefinitionConstants.ObjectRefAttribute); if (StringUtils.IsNullOrEmpty(objectRef)) { // a reference to the id of another object in the same XML file - objectRef = element.GetAttribute(ObjectDefinitionConstants.LocalRefAttribute); + objectRef = GetAttributeValue(element, ObjectDefinitionConstants.LocalRefAttribute); if (StringUtils.IsNullOrEmpty(objectRef)) { throw new ObjectDefinitionStoreException( @@ -974,15 +973,15 @@ namespace Spring.Objects.Factory.Xml private object ParseReference(XmlElement element, ObjectDefinitionParserHelper parserHelper, string name) { // is it a generic reference to any name of any object? - string objectRef = element.GetAttribute(ObjectDefinitionConstants.ObjectRefAttribute); + string objectRef = GetAttributeValue(element, ObjectDefinitionConstants.ObjectRefAttribute); if (StringUtils.IsNullOrEmpty(objectRef)) { // is it a reference to the id of another object in the same XML file? - objectRef = element.GetAttribute(ObjectDefinitionConstants.LocalRefAttribute); + objectRef = GetAttributeValue(element, ObjectDefinitionConstants.LocalRefAttribute); if (StringUtils.IsNullOrEmpty(objectRef)) { // is it a reference to the id of another object in a parent context? - objectRef = element.GetAttribute(ObjectDefinitionConstants.ParentAttribute); + objectRef = GetAttributeValue(element, ObjectDefinitionConstants.ParentAttribute); if (StringUtils.IsNullOrEmpty(objectRef)) { throw new ObjectDefinitionStoreException( @@ -998,7 +997,7 @@ namespace Spring.Objects.Factory.Xml private object ParseValueElement(XmlElement element, string name) { - string valueType = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute); + string valueType = GetAttributeValue(element, ObjectDefinitionConstants.TypeAttribute); if (StringUtils.IsNullOrEmpty(valueType)) { return ParseTextValueElement(element, name); @@ -1019,7 +1018,7 @@ namespace Spring.Objects.Factory.Xml private object ParseExpressionElement(XmlElement element, string name, ParserContext parserContext) { - string expression = element.GetAttribute(ObjectDefinitionConstants.ValueAttribute); + string expression = GetAttributeValue(element, ObjectDefinitionConstants.ValueAttribute); ExpressionHolder holder = new ExpressionHolder(expression); holder.Properties = ParsePropertyElements(name, element, parserContext); return holder; @@ -1042,7 +1041,7 @@ namespace Spring.Objects.Factory.Xml { ManagedList list = new ManagedList(); - string elementTypeName = element.GetAttribute("element-type"); + string elementTypeName = GetAttributeValue(element, "element-type"); if (StringUtils.HasText(elementTypeName)) { list.ElementTypeName = elementTypeName; @@ -1075,7 +1074,7 @@ namespace Spring.Objects.Factory.Xml protected Set ParseSetElement(XmlElement element, string name, ParserContext parserContext) { ManagedSet theSet = new ManagedSet(); - string elementTypeName = element.GetAttribute("element-type"); + string elementTypeName = GetAttributeValue(element, "element-type"); if (StringUtils.HasText(elementTypeName)) { theSet.ElementTypeName = elementTypeName; @@ -1108,8 +1107,8 @@ namespace Spring.Objects.Factory.Xml protected IDictionary ParseDictionaryElement(XmlElement element, string name, ParserContext parserContext) { ManagedDictionary dictionary = new ManagedDictionary(); - string keyTypeName = element.GetAttribute("key-type"); - string valueTypeName = element.GetAttribute("value-type"); + string keyTypeName = GetAttributeValue(element, "key-type"); + string valueTypeName = GetAttributeValue(element, "value-type"); if (StringUtils.HasText(keyTypeName)) { dictionary.KeyTypeName = keyTypeName; @@ -1288,9 +1287,9 @@ namespace Spring.Objects.Factory.Xml XmlNodeList addElements = element.GetElementsByTagName(ObjectDefinitionConstants.AddElement); foreach (XmlElement addElement in addElements) { - string key = addElement.GetAttribute(ObjectDefinitionConstants.KeyAttribute); - string value = addElement.GetAttribute(ObjectDefinitionConstants.ValueAttribute); - string delimiters = addElement.GetAttribute(ObjectDefinitionConstants.DelimitersAttribute); + string key = GetAttributeValue(addElement, ObjectDefinitionConstants.KeyAttribute); + string value = GetAttributeValue(addElement, ObjectDefinitionConstants.ValueAttribute); + string delimiters = GetAttributeValue(addElement, ObjectDefinitionConstants.DelimitersAttribute); if (StringUtils.HasText(delimiters)) { @@ -1440,5 +1439,38 @@ namespace Spring.Objects.Factory.Xml { return StringUtils.HasText(element.Prefix) ? element.Prefix : "spring"; } + + /// + /// Returns the value of the element's attribute or null, if the attribute is not specified. + /// + /// + /// This is a helper for bypassing the behavior of + /// to return if the attribute does not exist. + /// + protected static string GetAttributeValue(XmlElement element, string attributeName) + { + if (element.HasAttribute(attributeName)) + { + return element.GetAttribute(attributeName); + } + return null; + } + + /// + /// Returns the value of the element's attribute or , + /// if the attribute is not specified. + /// + /// + /// This is a helper for bypassing the behavior of + /// to return if the attribute does not exist. + /// + protected static string GetAttributeValue(XmlElement element, string attributeName, string defaultValue) + { + if (element.HasAttribute(attributeName)) + { + return element.GetAttribute(attributeName); + } + return defaultValue; + } } } diff --git a/src/Spring/Spring.Core/Util/StringUtils.cs b/src/Spring/Spring.Core/Util/StringUtils.cs index 90b8232d..29f89d73 100644 --- a/src/Spring/Spring.Core/Util/StringUtils.cs +++ b/src/Spring/Spring.Core/Util/StringUtils.cs @@ -493,6 +493,18 @@ namespace Spring.Util return !HasText(target); } + /// + /// Returns , if it contains non-whitespaces. null otherwise. + /// + public static string GetTextOrNull(string value) + { + if (!HasText(value)) + { + return null; + } + return value; + } + /// /// Strips first and last character off the string. /// diff --git a/src/Spring/Spring.Core/Validation/Config/ValidationNamespaceParser.cs b/src/Spring/Spring.Core/Validation/Config/ValidationNamespaceParser.cs index b51a0d00..4d16e8f1 100644 --- a/src/Spring/Spring.Core/Validation/Config/ValidationNamespaceParser.cs +++ b/src/Spring/Spring.Core/Validation/Config/ValidationNamespaceParser.cs @@ -137,12 +137,12 @@ namespace Spring.Validation.Config private IObjectDefinition ParseValidator(string id, XmlElement element, ParserContext parserContext) { string typeName = GetTypeName(element); - string parent = element.GetAttribute(ObjectDefinitionConstants.ParentAttribute); - string test = element.GetAttribute(ValidatorDefinitionConstants.TestAttribute); - string when = element.GetAttribute(ValidatorDefinitionConstants.WhenAttribute); - string validateAll = element.GetAttribute(ValidatorDefinitionConstants.CollectionValidateAllAttribute); - string context = element.GetAttribute(ValidatorDefinitionConstants.CollectionContextAttribute); - string includeElementsErrors = element.GetAttribute(ValidatorDefinitionConstants.CollectionIncludeElementsErrors); + string parent = GetAttributeValue(element, ObjectDefinitionConstants.ParentAttribute); + string test = GetAttributeValue(element, ValidatorDefinitionConstants.TestAttribute); + string when = GetAttributeValue(element, ValidatorDefinitionConstants.WhenAttribute); + string validateAll = GetAttributeValue(element, ValidatorDefinitionConstants.CollectionValidateAllAttribute); + string context = GetAttributeValue(element, ValidatorDefinitionConstants.CollectionContextAttribute); + string includeElementsErrors = GetAttributeValue(element, ValidatorDefinitionConstants.CollectionIncludeElementsErrors); string name = "validator: " + (StringUtils.HasText(id) ? id : this.definitionCount.ToString()); MutablePropertyValues properties = new MutablePropertyValues(); @@ -178,7 +178,7 @@ namespace Spring.Validation.Config switch (child.LocalName) { case ValidatorDefinitionConstants.PropertyElement: - string propertyName = child.GetAttribute(ValidatorDefinitionConstants.PropertyNameAttribute); + string propertyName = GetAttributeValue(child, ValidatorDefinitionConstants.PropertyNameAttribute); properties.Add(propertyName, base.ParsePropertyValue(child, name, parserContext)); break; case ValidatorDefinitionConstants.MessageElement: @@ -228,7 +228,7 @@ namespace Spring.Validation.Config /// Validator object definition. private IObjectDefinition ParseAndRegisterValidator(XmlElement element, ParserContext parserContext) { - string id = element.GetAttribute(ObjectDefinitionConstants.IdAttribute); + string id = GetAttributeValue(element, ObjectDefinitionConstants.IdAttribute); IObjectDefinition validator = ParseValidator(id, element, parserContext); if (StringUtils.HasText(id)) { @@ -245,7 +245,7 @@ namespace Spring.Validation.Config /// The name of the object type. private string GetTypeName(XmlElement element) { - string typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute); + string typeName = GetAttributeValue(element, ObjectDefinitionConstants.TypeAttribute); if (StringUtils.IsNullOrEmpty(typeName)) { return ValidatorTypePrefix + element.LocalName; @@ -261,13 +261,13 @@ namespace Spring.Validation.Config /// The error message action definition. private static IObjectDefinition ParseErrorMessageAction(XmlElement message, ParserContext parserContext) { - string messageId = message.GetAttribute(MessageConstants.IdAttribute); - string[] providers = message.GetAttribute(MessageConstants.ProvidersAttribute).Split(','); + string messageId = GetAttributeValue(message, MessageConstants.IdAttribute); + string[] providers = GetAttributeValue(message, MessageConstants.ProvidersAttribute).Split(','); ArrayList parameters = new ArrayList(); foreach (XmlElement param in message.ChildNodes) { - IExpression paramExpression = Expression.Parse(param.GetAttribute(MessageConstants.ParameterValueAttribute)); + IExpression paramExpression = Expression.Parse(GetAttributeValue(param, MessageConstants.ParameterValueAttribute)); parameters.Add(paramExpression); } @@ -276,7 +276,7 @@ namespace Spring.Validation.Config ctorArgs.AddGenericArgumentValue(messageId); ctorArgs.AddGenericArgumentValue(providers); - string when = message.GetAttribute(ValidatorDefinitionConstants.WhenAttribute); + string when = GetAttributeValue(message, ValidatorDefinitionConstants.WhenAttribute); MutablePropertyValues properties = new MutablePropertyValues(); if (StringUtils.HasText(when)) { @@ -303,8 +303,8 @@ namespace Spring.Validation.Config /// Generic validation action definition. private IObjectDefinition ParseGenericAction(XmlElement element, ParserContext parserContext) { - string typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute); - string when = element.GetAttribute(ValidatorDefinitionConstants.WhenAttribute); + string typeName = GetAttributeValue(element, ObjectDefinitionConstants.TypeAttribute); + string when = GetAttributeValue(element, ValidatorDefinitionConstants.WhenAttribute); MutablePropertyValues properties = base.ParsePropertyElements("validator:action", element, parserContext); if (StringUtils.HasText(when)) { @@ -327,8 +327,8 @@ namespace Spring.Validation.Config private IObjectDefinition ParseValidatorReference(XmlElement element, ParserContext parserContext) { string typeName = "Spring.Validation.ValidatorReference, Spring.Core"; - string name = element.GetAttribute(ValidatorDefinitionConstants.ReferenceNameAttribute); - string context = element.GetAttribute(ValidatorDefinitionConstants.ReferenceContextAttribute); + string name = GetAttributeValue(element, ValidatorDefinitionConstants.ReferenceNameAttribute); + string context = GetAttributeValue(element, ValidatorDefinitionConstants.ReferenceContextAttribute); MutablePropertyValues properties = new MutablePropertyValues(); properties.Add("Name", name); diff --git a/src/Spring/Spring.Data/Dao/Support/PersistenceExceptionTranslationInterceptor.cs b/src/Spring/Spring.Data/Dao/Support/PersistenceExceptionTranslationInterceptor.cs index 45fb8425..e41345c3 100644 --- a/src/Spring/Spring.Data/Dao/Support/PersistenceExceptionTranslationInterceptor.cs +++ b/src/Spring/Spring.Data/Dao/Support/PersistenceExceptionTranslationInterceptor.cs @@ -118,7 +118,7 @@ namespace Spring.Dao.Support IListableObjectFactory owningFactory = value as IListableObjectFactory; if (owningFactory == null) { - throw new ArgumentException("Cannot use IPersistenceExceptionTranslator autodetection without IListableBeanFactory"); + throw new ArgumentException("Cannot use IPersistenceExceptionTranslator autodetection without IListableObjectFactory"); } this.persistenceExceptionTranslator = DetectPersistenceExceptionTranslators(owningFactory); } diff --git a/src/Spring/Spring.Data/Data/Config/DatabaseNamespaceParser.cs b/src/Spring/Spring.Data/Data/Config/DatabaseNamespaceParser.cs index 5b7fc754..37bf29a6 100644 --- a/src/Spring/Spring.Data/Data/Config/DatabaseNamespaceParser.cs +++ b/src/Spring/Spring.Data/Data/Config/DatabaseNamespaceParser.cs @@ -87,8 +87,8 @@ namespace Spring.Data.Config /// /// public override IObjectDefinition ParseElement(XmlElement element, ParserContext parserContext) - { - string id = element.GetAttribute(ObjectDefinitionConstants.IdAttribute); + { + string id = GetAttributeValue(element, ObjectDefinitionConstants.IdAttribute); IConfigurableObjectDefinition databaseConfiguration = ParseDatabaseDefinition(element, id, parserContext); if (!StringUtils.HasText(id)) { @@ -122,9 +122,9 @@ namespace Spring.Data.Config private IConfigurableObjectDefinition ParseDatabaseConfigurer(XmlElement element, string name, ParserContext parserContext) { - string typeName = GetTypeName(element); - string providerNameAttribute = element.GetAttribute(DbProviderFactoryObjectConstants.ProviderNameAttribute); - string connectionString = element.GetAttribute(DbProviderFactoryObjectConstants.ConnectionStringAttribute); + string typeName = GetTypeName(element); + string providerNameAttribute = GetAttributeValue(element, DbProviderFactoryObjectConstants.ProviderNameAttribute); + string connectionString = GetAttributeValue(element, DbProviderFactoryObjectConstants.ConnectionStringAttribute); MutablePropertyValues properties = new MutablePropertyValues(); if (StringUtils.HasText(providerNameAttribute)) @@ -150,8 +150,8 @@ namespace Spring.Data.Config /// The element. /// The name of the object type. private string GetTypeName(XmlElement element) - { - string typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute); + { + string typeName = GetAttributeValue(element, ObjectDefinitionConstants.TypeAttribute); if (StringUtils.IsNullOrEmpty(typeName)) { return DatabaseTypePrefix + element.LocalName; diff --git a/src/Spring/Spring.Data/Transaction/Config/AttributeDrivenObjectDefinitionParser.cs b/src/Spring/Spring.Data/Transaction/Config/AttributeDrivenObjectDefinitionParser.cs index 440d6576..43184152 100644 --- a/src/Spring/Spring.Data/Transaction/Config/AttributeDrivenObjectDefinitionParser.cs +++ b/src/Spring/Spring.Data/Transaction/Config/AttributeDrivenObjectDefinitionParser.cs @@ -64,9 +64,9 @@ namespace Spring.Transaction.Config /// protected override AbstractObjectDefinition ParseInternal(XmlElement element, ParserContext parserContext) { - ConfigureAutoProxyCreator(parserContext, element); - - string transactionManagerName = element.GetAttribute(TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE); + ConfigureAutoProxyCreator(parserContext, element); + + string transactionManagerName = GetAttributeValue(element, TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE); Type sourceType = typeof (AttributesTransactionAttributeSource); //Create the TransactionInterceptor definition. @@ -81,7 +81,7 @@ namespace Spring.Transaction.Config advisorDefinition.PropertyValues.Add(TRANSACTION_INTERCEPTOR, interceptorDefinition); if (element.HasAttribute(ORDER)) { - advisorDefinition.PropertyValues.Add(ORDER, element.GetAttribute(ORDER)); + advisorDefinition.PropertyValues.Add(ORDER, GetAttributeValue(element, ORDER)); } return advisorDefinition; @@ -96,8 +96,8 @@ namespace Spring.Transaction.Config { AopNamespaceUtils.RegisterAutoProxyCreatorIfNecessary(parserContext, element); - bool proxyTargetClass = - parserContext.ParserHelper.IsTrueStringValue(element.GetAttribute(PROXY_TARGET_TYPE)); + bool proxyTargetClass = + parserContext.ParserHelper.IsTrueStringValue(GetAttributeValue(element, PROXY_TARGET_TYPE)); if (proxyTargetClass) { AopNamespaceUtils.ForceAutoProxyCreatorToUseDecoratorProxy(parserContext.Registry); diff --git a/src/Spring/Spring.Data/Transaction/Config/TxAdviceObjectDefinitionParser.cs b/src/Spring/Spring.Data/Transaction/Config/TxAdviceObjectDefinitionParser.cs index 749b4c22..e620e5f1 100644 --- a/src/Spring/Spring.Data/Transaction/Config/TxAdviceObjectDefinitionParser.cs +++ b/src/Spring/Spring.Data/Transaction/Config/TxAdviceObjectDefinitionParser.cs @@ -62,8 +62,8 @@ namespace Spring.Transaction.Config protected override void DoParse(XmlElement element, ParserContext parserContext, ObjectDefinitionBuilder builder) { - builder.AddPropertyReference(TxNamespaceUtils.TRANSACTION_MANAGER_PROPERTY, - element.GetAttribute(TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE)); + builder.AddPropertyReference(TxNamespaceUtils.TRANSACTION_MANAGER_PROPERTY, + GetAttributeValue(element, TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE)); XmlNodeList txAttributes = element.SelectNodes("*[local-name()='attributes' and namespace-uri()='" + element.NamespaceURI + "']"); if (txAttributes.Count > 1 ) { @@ -94,15 +94,15 @@ namespace Spring.Transaction.Config XmlNodeList methods = element.SelectNodes("*[local-name()='method' and namespace-uri()='" + element.NamespaceURI + "']"); ManagedDictionary transactionAttributeMap = new ManagedDictionary(); foreach (XmlElement methodElement in methods) - { - string name = methodElement.GetAttribute("name"); + { + string name = GetAttributeValue(methodElement, "name"); TypedStringValue nameHolder = new TypedStringValue(name); - RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute(); - string propagation = methodElement.GetAttribute(PROPAGATION); - string isolation = methodElement.GetAttribute(ISOLATION); - string timeout = methodElement.GetAttribute(TIMEOUT); - string readOnly = methodElement.GetAttribute(READ_ONLY); + RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute(); + string propagation = GetAttributeValue(methodElement, PROPAGATION); + string isolation = GetAttributeValue(methodElement, ISOLATION); + string timeout = GetAttributeValue(methodElement, TIMEOUT); + string readOnly = GetAttributeValue(methodElement, READ_ONLY); if (StringUtils.HasText(propagation)) { attribute.PropagationBehavior = (TransactionPropagation) Enum.Parse(typeof (TransactionPropagation), propagation, true); @@ -124,30 +124,28 @@ namespace Spring.Transaction.Config } } if (StringUtils.HasText(readOnly)) - { - attribute.ReadOnly = Boolean.Parse(methodElement.GetAttribute(READ_ONLY)); + { + attribute.ReadOnly = Boolean.Parse(GetAttributeValue(methodElement, READ_ONLY)); } IList rollbackRules = new LinkedList(); if (methodElement.HasAttribute(ROLLBACK_FOR)) - { - string rollbackForValue = methodElement.GetAttribute(ROLLBACK_FOR); + { + string rollbackForValue = GetAttributeValue(methodElement, ROLLBACK_FOR); AddRollbackRuleAttributesTo(rollbackRules, rollbackForValue); } if (methodElement.HasAttribute(NO_ROLLBACK_FOR)) - { - string noRollbackForValue = methodElement.GetAttribute(NO_ROLLBACK_FOR); + { + string noRollbackForValue = GetAttributeValue(methodElement, NO_ROLLBACK_FOR); AddNoRollbackRuleAttributesTo(rollbackRules, noRollbackForValue); } attribute.RollbackRules = rollbackRules; transactionAttributeMap[nameHolder] = attribute; - - - } - ObjectDefinitionBuilder builder = - parserContext.ParserHelper.CreateRootObjectDefinitionBuilder(typeof (NameMatchTransactionAttributeSource)); + ObjectDefinitionBuilder builder = parserContext + .ParserHelper + .CreateRootObjectDefinitionBuilder(typeof (NameMatchTransactionAttributeSource)); builder.AddPropertyValue(NAME_MAP, transactionAttributeMap); return builder.ObjectDefinition; diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs index 598b7356..f228bdf9 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs @@ -24,6 +24,7 @@ using System; using System.Collections; using System.Globalization; using System.Reflection; +using System.Runtime.Serialization; using DotNetMock.Dynamic; using NUnit.Framework; using Spring.Core.IO; @@ -1664,6 +1665,44 @@ namespace Spring.Objects.Factory Assert.IsNotNull(c); } + #region GetObjectNamesForTypeFindsFactoryObjects + + private class A : IFactoryObject, ISerializable + { + public object GetObject() + { + throw new NotImplementedException(); + } + + public Type ObjectType + { + get { throw new NotImplementedException(); } + } + + public bool IsSingleton + { + get { throw new NotImplementedException(); } + } + + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + throw new NotImplementedException(); + } + } + + #endregion + + [Test] + public void GetObjectNamesForTypeFindsFactoryObjects() + { + DefaultListableObjectFactory of = new DefaultListableObjectFactory(); + of.RegisterObjectDefinition("mod", new RootObjectDefinition(typeof(A))); + + string[] names = of.GetObjectNamesForType(typeof (ISerializable), false, false); + Assert.IsNotEmpty(names); + Assert.AreEqual("&mod", names[0]); + } + #region Helper Classes public interface IParent diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs index e464d5d2..99a42a4e 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs @@ -83,9 +83,9 @@ namespace Spring.Objects.Factory IConfigurableListableObjectFactory of = (IConfigurableListableObjectFactory) mocks.DynamicMock(typeof (IConfigurableListableObjectFactory)); IConfigurableListableObjectFactory ofParent = (IConfigurableListableObjectFactory) mocks.DynamicMock(typeof (IConfigurableListableObjectFactory)); - Expect.Call(of.GetObjectDefinitionNames()).Return(new string[] { "objA", "objB", "objC" }); + Expect.Call(of.GetObjectNamesForType(typeof(object))).Return(new string[] { "objA", "objB", "objC" }); Expect.Call(((IHierarchicalObjectFactory)of).ParentObjectFactory).Return(ofParent); - Expect.Call(ofParent.GetObjectDefinitionNames()).Return(new string[] { "obj2A", "objB", "obj2C" }); + Expect.Call(ofParent.GetObjectNamesForType(typeof(object))).Return(new string[] { "obj2A", "objB", "obj2C" }); mocks.ReplayAll(); @@ -109,6 +109,23 @@ namespace Spring.Objects.Factory Assert.IsTrue(names.Contains("testFactory2")); } + [Test] + public void ObjectNamesForTypeIncludingAncestorsExcludesObjectsFromParentWhenLocalObjectDefined() + { + DefaultListableObjectFactory root = new DefaultListableObjectFactory(); + root.RegisterObjectDefinition( "excludeLocalObject", new RootObjectDefinition(typeof(ArrayList)) ); + DefaultListableObjectFactory child = new DefaultListableObjectFactory(root); + child.RegisterObjectDefinition("excludeLocalObject", new RootObjectDefinition(typeof(Hashtable))); + + IList names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(child, typeof (ArrayList)); + // "excludeLocalObject" matches on the parent, but not the local object definition + Assert.AreEqual(0, names.Count); + + names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(child, typeof (ArrayList), true, true); + // "excludeLocalObject" matches on the parent, but not the local object definition + Assert.AreEqual(0, names.Count); + } + #if NET_2_0 [Test] public void ObjectNamesForTypeIncludingAncestorsPreserveOrderOfRegistration() @@ -171,12 +188,14 @@ namespace Spring.Objects.Factory object testFactory1 = _factory.GetObject("testFactory1"); IDictionary objects = ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(_factory, typeof (ITestObject), true, false); - Assert.AreEqual(2, objects.Count); + Assert.AreEqual(3, objects.Count); Assert.AreEqual(test3, objects["test3"]); Assert.AreEqual(test, objects["test"]); + Assert.AreEqual(testFactory1, objects["testFactory1"]); objects = ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(_factory, typeof (ITestObject), false, false); - Assert.AreEqual(1, objects.Count); + Assert.AreEqual(2, objects.Count); Assert.AreEqual(test, objects["test"]); + Assert.AreEqual(testFactory1, objects["testFactory1"]); objects = ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(_factory, typeof (ITestObject), false, true); Assert.AreEqual(2, objects.Count); Assert.AreEqual(test, objects["test"]); @@ -205,6 +224,19 @@ namespace Spring.Objects.Factory ObjectFactoryUtils.ObjectOfTypeIncludingAncestors(_factory, typeof (ITestObject), true, true); } + [Test] + public void ObjectOfTypeIncludingAncestorsExcludesObjectsFromParentWhenLocalObjectDefined() + { + DefaultListableObjectFactory root = new DefaultListableObjectFactory(); + root.RegisterObjectDefinition("excludeLocalObject", new RootObjectDefinition(typeof(ArrayList))); + DefaultListableObjectFactory child = new DefaultListableObjectFactory(root); + child.RegisterObjectDefinition("excludeLocalObject", new RootObjectDefinition(typeof(Hashtable))); + + IDictionary objectEntries = ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(child, typeof(ArrayList), true, true); + // "excludeLocalObject" matches on the parent, but not the local object definition + Assert.AreEqual(0, objectEntries.Count); + } + [Test] public void NoObjectsOfTypeIncludingAncestors() {