From 773f3146dab86afae11fa359f9682ec4a18a5352 Mon Sep 17 00:00:00 2001
From: Thomas Trageser
Date: Thu, 23 Aug 2012 13:14:12 +0100
Subject: [PATCH 1/6] Add autowire by attribute for fields, properties, methods
and constructors
---
.../Spring.Core/Core/MethodParameter.cs | 8 +
.../Factory/Attributes/AutowiredAttribute.cs | 74 ++
.../AutowiredAttributeObjectPostProcessor.cs | 639 ++++++++++++++++++
.../Factory/Attributes/InjectionMetadata.cs | 112 +++
.../Factory/Attributes/QualifierAttribute.cs | 32 +
.../Factory/Config/DependencyDescriptor.cs | 148 +++-
.../Support/DefaultListableObjectFactory.cs | 65 +-
.../Spring.Core/Spring.Core.2010.csproj | 4 +
.../AutowireAttributeCollectionTests.cs | 160 +++++
.../AutowireAttributeConstructorTest.cs | 343 ++++++++++
.../Attributes/AutowireAttributeFieldTest.cs | 290 ++++++++
.../AutowireAttributeMethodsTests.cs | 371 ++++++++++
.../AutowireAttributePropertyTest.cs | 254 +++++++
.../Spring.Core.Tests.2010.csproj | 5 +
14 files changed, 2501 insertions(+), 4 deletions(-)
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttribute.cs
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Attributes/InjectionMetadata.cs
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAttribute.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeCollectionTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeConstructorTest.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeFieldTest.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeMethodsTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributePropertyTest.cs
diff --git a/src/Spring/Spring.Core/Core/MethodParameter.cs b/src/Spring/Spring.Core/Core/MethodParameter.cs
index 292720f4..1a923378 100644
--- a/src/Spring/Spring.Core/Core/MethodParameter.cs
+++ b/src/Spring/Spring.Core/Core/MethodParameter.cs
@@ -136,5 +136,13 @@ namespace Spring.Core
{
get { return constructorInfo; }
}
+
+ public Attribute[] GetParameterAttributes()
+ {
+ if (methodInfo != null)
+ return Attribute.GetCustomAttributes(methodInfo.GetParameters()[parameterIndex]);
+ else
+ return Attribute.GetCustomAttributes(constructorInfo.GetParameters()[parameterIndex]);
+ }
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttribute.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttribute.cs
new file mode 100644
index 00000000..9be3154a
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttribute.cs
@@ -0,0 +1,74 @@
+#region License
+
+/*
+ * Copyright © 2010-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ ///
+ /// Marks a constructor, field, propery or config method as to be
+ /// autowired by Spring's dependency injection facilities.
+ ///
+ /// Only one constructor (at max) of any given bean class may carry this
+ /// annotation, indicating the constructor to autowire when used as a Spring
+ /// bean. Such a constructor does not have to be public.
+ ///
+ /// Fields are injected right after construction of a object, before any
+ /// config methods are invoked. Such a config field does not have to be public.
+ ///
+ /// Config methods may have an arbitrary name and any number of arguments;
+ /// each of those arguments will be autowired with a matching bean in the
+ /// Spring container. Object property setter methods are effectively just
+ /// a special case of such a general config method. Such config methods
+ /// do not have to be public.
+ ///
+ /// In the case of multiple argument methods, the 'required' parameter is
+ /// applicable for all arguments.
+ ///
+ /// In case of a {@link java.util.Collection} or {@link java.util.Map}
+ /// dependency type, the container will autowire all beans matching the
+ /// declared value type. In case of a Map, the keys must be declared as
+ /// type String and will be resolved to the corresponding bean names.
+ ///
+ /// Note that actual injection is performed through a
+ /// {@link org.springframework.beans.factory.config.BeanPostProcessor
+ /// BeanPostProcessor} which in turn means that you cannot
+ /// use {@code @Autowired} to inject references into
+ /// {@link org.springframework.beans.factory.config.BeanPostProcessor
+ /// BeanPostProcessor} or
+ /// {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}
+ /// types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
+ /// class (which, by default, checks for the presence of this annotation).
+ ///
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Constructor)]
+ public class AutowiredAttribute : Attribute
+ {
+ private bool _required = true;
+
+ ///
+ /// Defines it Autowired PostProcessor should fail if object is not set
+ ///
+ public bool Required
+ {
+ get { return _required; }
+ set { _required = value; }
+ }
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs
new file mode 100644
index 00000000..07c74ea8
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs
@@ -0,0 +1,639 @@
+#region License
+
+/*
+ * Copyright © 2010-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Reflection;
+using System.Linq;
+using Spring.Collections;
+using Spring.Core;
+using Spring.Objects.Factory.Config;
+using Common.Logging;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+
+ ///
+ /// implementation
+ /// that autowires annotated fields, properties and arbitrary config methods.
+ /// Such members to be injected are detected through an attribute: by default,
+ /// Spring's .
+ ///
+ /// Only one constructor (at max) of any given bean class may carry this
+ /// annotation with the 'required' parameter set to true,
+ /// indicating the constructor to autowire when used as a Spring bean.
+ /// If multiple non-required constructors carry the annotation, they
+ /// will be considered as candidates for autowiring. The constructor with
+ /// the greatest number of dependencies that can be satisfied by matching
+ /// beans in the Spring container will be chosen. If none of the candidates
+ /// can be satisfied, then a default constructor (if present) will be used.
+ /// An annotated constructor does not have to be public.
+ ///
+ /// Fields are injected right after construction of a bean, before any
+ /// config methods are invoked. Such a config field does not have to be public.
+ ///
+ /// Config methods may have an arbitrary name and any number of arguments; each of
+ /// those arguments will be autowired with a matching bean in the Spring container.
+ /// Bean property setter methods are effectively just a special case of such a
+ /// general config method. Config methods do not have to be public.
+ ///
+ /// Note: A default AutowiredAttributeObjectPostProcessor will be registered
+ /// by the "context:annotation-config" and "context:component-scan" XML tags.
+ /// Remove or turn off the default annotation configuration there if you intend
+ /// to specify a custom AutowiredAnnotationBeanPostProcessor bean definition.
+ /// NOTE: Annotation injection will be performed before XML injection;
+ /// thus the latter configuration will override the former for properties wired through
+ /// both approaches.
+ ///
+ public class AutowiredAttributeObjectPostProcessor : InstantiationAwareObjectPostProcessorAdapter,
+ IObjectFactoryAware, IOrdered
+ {
+ private static readonly ILog Logger = LogManager.GetLogger();
+
+ private int _order = int.MaxValue - 2;
+
+ private static IConfigurableListableObjectFactory _objectFactory;
+
+ private SynchronizedHashtable _candidateConstructorsCache = new SynchronizedHashtable();
+
+ private readonly IDictionary _injectionMetadataCache =
+ new Dictionary();
+
+ private Type _autowiredPropertyType = typeof (AutowiredAttribute);
+
+ ///
+ /// Return the order value of this object, where a higher value means greater in
+ /// terms of sorting.
+ ///
+ ///
+ /// Normally starting with 0 or 1, with indicating
+ /// greatest. Same order values will result in arbitrary positions for the affected
+ /// objects.
+ ///
Higher value can be interpreted as lower priority, consequently the first object
+ /// has highest priority.
+ ///
+ ///
+ ///
+ /// The order value.
+ ///
+ public int Order
+ {
+ get { return _order; }
+ private set { _order = value; }
+ }
+
+
+ ///
+ /// Callback that supplies the owning factory to an object instance.
+ ///
+ ///
+ /// Owning
+ /// (may not be ). The object can immediately
+ /// call methods on the factory.
+ ///
+ ///
+ /// Invoked after population of normal object properties but before an init
+ /// callback like 's
+ ///
+ /// method or a custom init-method.
+ ///
+ ///
+ /// In case of initialization errors.
+ ///
+ public IObjectFactory ObjectFactory
+ {
+ set { _objectFactory = (IConfigurableListableObjectFactory) value; }
+ }
+
+
+ ///
+ /// Sets the used AutowiredAttributeType during the scan
+ ///
+ public Type AutowiredAttributeType
+ {
+ get { return _autowiredPropertyType; }
+ set { _autowiredPropertyType = value; }
+ }
+
+
+ ///
+ /// Determines the candidate constructors to use for the given object.
+ ///
+ /// The raw Type of the object.
+ /// Name of the object.
+ /// The candidate constructors, or null if none specified
+ /// in case of errors
+ public override ConstructorInfo[] DetermineCandidateConstructors(Type objectType, string objectName)
+ {
+ // Quick check on the concurrent map first, with minimal locking.
+ ConstructorInfo[] candidateConstructors = _candidateConstructorsCache.ContainsKey(objectType)
+ ? (ConstructorInfo[])_candidateConstructorsCache[objectType]
+ : null;
+ if (candidateConstructors == null)
+ {
+ lock (_candidateConstructorsCache)
+ {
+ candidateConstructors = _candidateConstructorsCache.ContainsKey(objectType)
+ ? (ConstructorInfo[])_candidateConstructorsCache[objectType]
+ : null;
+ if (candidateConstructors == null)
+ {
+ ConstructorInfo[] rawCandidates = objectType.GetConstructors();
+ IList candidates = new List(rawCandidates.Length);
+ ConstructorInfo requiredConstructor = null;
+ ConstructorInfo defaultConstructor = null;
+ foreach(var candidate in rawCandidates)
+ {
+ AutowiredAttribute attr =
+ Attribute.GetCustomAttribute(candidate, typeof (AutowiredAttribute)) as AutowiredAttribute;
+ if (attr != null)
+ {
+ if (requiredConstructor != null) {
+ throw new ObjectCreationException("Invalid autowire-marked constructor: " + candidate +
+ ". Found another constructor with 'required' Autowired annotation: " +
+ requiredConstructor);
+ }
+ if (candidate.GetParameters().Length == 0)
+ {
+ throw new InvalidOperationException("Autowired annotation requires at least one argument: " + candidate);
+ }
+ if (attr.Required)
+ {
+ if (candidates.Count > 0)
+ {
+ throw new ObjectCreationException(
+ "Invalid autowire-marked constructors: " + candidates +
+ ". Found another constructor with 'required' Autowired annotation: " +
+ requiredConstructor);
+ }
+ requiredConstructor = candidate;
+ }
+ candidates.Add(candidate);
+ }
+ else if (candidate.GetParameters().Length == 0)
+ {
+ defaultConstructor = candidate;
+ }
+ }
+ if (candidates.Count > 0)
+ {
+ // Add default constructor to list of optional constructors, as fallback.
+ if (requiredConstructor == null && defaultConstructor != null) {
+ candidates.Add(defaultConstructor);
+ }
+ candidateConstructors = candidates.ToArray();
+ }
+ else {
+ candidateConstructors = new ConstructorInfo[0];
+ }
+ _candidateConstructorsCache.Add(objectType, candidateConstructors);
+ }
+ }
+ }
+ return (candidateConstructors.Length > 0 ? candidateConstructors : null);
+ }
+
+
+ ///
+ /// Finds autowire candidates and verifies them
+ ///
+ ///
+ /// The of the target object that is to be
+ /// instantiated.
+ ///
+ ///
+ /// The name of the target object.
+ ///
+ ///
+ /// The object to expose instead of a default instance of the target
+ /// object.
+ ///
+ ///
+ /// In the case of any errors.
+ ///
+ ///
+ ///
+ public override object PostProcessBeforeInstantiation(Type objectType, string objectName)
+ {
+ var objectDefinition = _objectFactory.GetObjectDefinition(objectName) as RootObjectDefinition;
+ if (objectType != null)
+ {
+ var metadata = FindAutowiringMetadata(objectType);
+ metadata.CheckConfigMembers(objectDefinition);
+ }
+ return null;
+ }
+
+ ///
+ /// Injects autoried annotated properties, fields, methods into objectInstance
+ ///
+ ///
+ ///
+ ///
+ /// Name of the object.
+ /// The actual property values to apply to the given object (can be the
+ /// passed-in PropertyValues instances0 or null to skip property population.
+ public override IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, IList pis,
+ object objectInstance, string objectName)
+ {
+ var metadata = FindAutowiringMetadata(objectInstance.GetType());
+ try
+ {
+ metadata.Inject(objectInstance, objectName, pvs);
+ }
+ catch (Exception ex)
+ {
+ throw new ObjectCreationException(objectName, "Injection of autowired dependencies failed", ex);
+ }
+ return pvs;
+ }
+
+
+ private InjectionMetadata FindAutowiringMetadata(Type objectType)
+ {
+ // Quick check on the concurrent map first, with minimal locking.
+ InjectionMetadata metadata = null;
+ if (_injectionMetadataCache.ContainsKey(objectType))
+ metadata = _injectionMetadataCache[objectType];
+
+ if (metadata == null)
+ {
+ lock (_injectionMetadataCache)
+ {
+ if (!_injectionMetadataCache.ContainsKey(objectType))
+ {
+ metadata = BuildAutowiringMetadata(objectType);
+ _injectionMetadataCache.Add(objectType, metadata);
+ }
+ }
+ }
+ return metadata;
+ }
+
+ private InjectionMetadata BuildAutowiringMetadata(Type objectType)
+ {
+ var elements = new List();
+
+ do
+ {
+ var currElements = new List();
+ foreach (
+ var property in
+ objectType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
+ {
+ var attr = Attribute.GetCustomAttribute(property, _autowiredPropertyType) as AutowiredAttribute;
+ if (attr != null && property.DeclaringType == objectType)
+ currElements.Add(new AutowiredPropertyElement(property, attr.Required));
+ }
+ foreach (
+ var field in
+ objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
+ {
+ var attr = Attribute.GetCustomAttribute(field, _autowiredPropertyType) as AutowiredAttribute;
+ if (attr != null && field.DeclaringType == objectType)
+ currElements.Add(new AutowiredFieldElement(field, attr.Required));
+ }
+ foreach (
+ var method in
+ objectType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
+ {
+ var attr = Attribute.GetCustomAttribute(method, _autowiredPropertyType) as AutowiredAttribute;
+ if (attr != null && method.DeclaringType == objectType)
+ {
+ if (method.IsStatic)
+ {
+ Logger.Warn(
+ m => m("Autowired annotation is not supported on static methods: " + method.Name));
+ continue;
+ }
+ if (method.IsGenericMethod)
+ {
+ Logger.Warn(
+ m => m("Autowired annotation is not supported on generic methods: " + method.Name));
+ continue;
+ }
+ currElements.Add(new AutowiredMethodElement(method, attr.Required));
+ }
+ }
+ elements.InsertRange(0, currElements);
+ objectType = objectType.BaseType;
+ } while (objectType != null && objectType != typeof (Object));
+
+ return new InjectionMetadata(objectType, elements);
+ }
+
+ ///
+ /// Register the specified bean as dependent on the autowired beans.
+ ///
+ private static void RegisterDependentObjects(string objectName, IList autowiredObjectNames)
+ {
+ if (objectName == null) return;
+
+ var objectDefinition = _objectFactory.GetObjectDefinition(objectName) as RootObjectDefinition;
+ IList dependsOn = new List(objectDefinition.DependsOn);
+ foreach (var name in autowiredObjectNames)
+ {
+ var autowiredObjectName = name as string;
+ if (!dependsOn.Contains(autowiredObjectName))
+ {
+ dependsOn.Add(autowiredObjectName);
+ Logger.Debug(
+ m =>
+ m("Autowiring by type from object name '{0}' to object named '{1}'", objectName,
+ autowiredObjectName));
+ }
+ }
+ objectDefinition.DependsOn = dependsOn;
+ }
+
+ private static object ResolvedCachedArgument(String objectName, Object cachedArgument)
+ {
+ if (cachedArgument is DependencyDescriptor)
+ {
+ var descriptor = (DependencyDescriptor) cachedArgument;
+ return _objectFactory.ResolveDependency(descriptor, objectName, null);
+ }
+ else if (cachedArgument is RuntimeObjectReference)
+ {
+ return _objectFactory.GetObject(((RuntimeObjectReference) cachedArgument).ObjectName);
+ }
+ else
+ {
+ return cachedArgument;
+ }
+ }
+
+ ///
+ /// Class representing injection information about an annotated field.
+ ///
+ private class AutowiredPropertyElement : InjectionMetadata.InjectedElement
+ {
+
+ private readonly bool _required;
+
+ private bool _cached = false;
+
+ private Object _cachedFieldValue;
+
+ public AutowiredPropertyElement(PropertyInfo property, bool required)
+ : base(property)
+ {
+ _required = required;
+ }
+
+ public override void Inject(Object instance, String objectName, IPropertyValues pvs)
+ {
+ var property = (PropertyInfo) _member;
+ try
+ {
+ Object value;
+ if (_cached)
+ {
+ value = ResolvedCachedArgument(objectName, _cachedFieldValue);
+ }
+ else
+ {
+ var descriptor = new DependencyDescriptor(property, _required);
+ IList autowiredObjectNames = new ArrayList();
+ value = _objectFactory.ResolveDependency(descriptor, objectName, autowiredObjectNames);
+ lock (this)
+ {
+ if (!_cached)
+ {
+ if (value != null || _required)
+ {
+ _cachedFieldValue = descriptor;
+ RegisterDependentObjects(objectName, autowiredObjectNames);
+ if (autowiredObjectNames.Count == 1)
+ {
+ var autowiredBeanName = autowiredObjectNames[0] as string;
+ if (_objectFactory.ContainsObject(autowiredBeanName))
+ {
+ if (_objectFactory.IsTypeMatch(autowiredBeanName, property.GetType()))
+ {
+ _cachedFieldValue = new RuntimeObjectReference(autowiredBeanName);
+ }
+ }
+ }
+ }
+ else
+ {
+ _cachedFieldValue = null;
+ }
+ _cached = true;
+ }
+ }
+ }
+ if (value != null)
+ {
+ property.SetValue(instance, value, null);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new ObjectCreationException("Could not autowire property: " + property, ex);
+ }
+ }
+ }
+
+ ///
+ /// Class representing injection information about an annotated field.
+ ///
+ private class AutowiredFieldElement : InjectionMetadata.InjectedElement
+ {
+
+ private readonly bool _required;
+
+ private bool _cached = false;
+
+ private Object _cachedFieldValue;
+
+ public AutowiredFieldElement(FieldInfo field, bool required)
+ : base(field)
+ {
+ _required = required;
+ }
+
+ public override void Inject(Object instance, String objectName, IPropertyValues pvs)
+ {
+ var field = (FieldInfo) _member;
+ try
+ {
+ Object value;
+ if (_cached)
+ {
+ value = ResolvedCachedArgument(objectName, _cachedFieldValue);
+ }
+ else
+ {
+ var descriptor = new DependencyDescriptor(field, _required);
+ IList autowiredObjectNames = new ArrayList();
+ value = _objectFactory.ResolveDependency(descriptor, objectName, autowiredObjectNames);
+ lock (this)
+ {
+ if (!_cached)
+ {
+ if (value != null || _required)
+ {
+ _cachedFieldValue = descriptor;
+ RegisterDependentObjects(objectName, autowiredObjectNames);
+ if (autowiredObjectNames.Count == 1)
+ {
+ var autowiredBeanName = autowiredObjectNames[0] as string;
+ if (_objectFactory.ContainsObject(autowiredBeanName))
+ {
+ if (_objectFactory.IsTypeMatch(autowiredBeanName, field.GetType()))
+ {
+ _cachedFieldValue = new RuntimeObjectReference(autowiredBeanName);
+ }
+ }
+ }
+ }
+ else
+ {
+ _cachedFieldValue = null;
+ }
+ _cached = true;
+ }
+ }
+ }
+ if (value != null)
+ {
+ field.SetValue(instance, value);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new ObjectCreationException("Could not autowire field: " + field, ex);
+ }
+ }
+ }
+
+ ///
+ /// Class representing injection information about an annotated method.
+ ///
+ private class AutowiredMethodElement : InjectionMetadata.InjectedElement
+ {
+ private readonly bool _required;
+
+ private bool _cached = false;
+
+ private volatile Object[] _cachedMethodArguments;
+
+ public AutowiredMethodElement(MethodInfo method, bool required)
+ : base(method)
+ {
+ _required = required;
+ }
+
+ public override void Inject(Object target, string objectName, IPropertyValues pvs)
+ {
+ MethodInfo method = _member as MethodInfo;
+ try
+ {
+ Object[] arguments;
+ if (_cached)
+ {
+ arguments = ResolveCachedArguments(objectName);
+ }
+ else
+ {
+ Type[] paramTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
+ arguments = new Object[paramTypes.Length];
+ var descriptors = new DependencyDescriptor[paramTypes.Length];
+ IList autowiredBeanNames = new ArrayList();
+ for (int i = 0; i < arguments.Length; i++)
+ {
+ MethodParameter methodParam = new MethodParameter(method, i);
+ descriptors[i] = new DependencyDescriptor(methodParam, _required);
+ arguments[i] = _objectFactory.ResolveDependency(descriptors[i], objectName,
+ autowiredBeanNames);
+ if (arguments[i] == null && !_required)
+ {
+ arguments = null;
+ break;
+ }
+ }
+ lock (this)
+ {
+ if (!_cached)
+ {
+ if (arguments != null)
+ {
+ _cachedMethodArguments = new Object[arguments.Length];
+ for (int i = 0; i < arguments.Length; i++)
+ {
+ _cachedMethodArguments[i] = descriptors[i];
+ }
+ RegisterDependentObjects(objectName, autowiredBeanNames);
+ if (autowiredBeanNames.Count == paramTypes.Length)
+ {
+ for (int i = 0; i < paramTypes.Length; i++)
+ {
+ string autowiredBeanName = autowiredBeanNames[i] as string;
+ if (_objectFactory.ContainsObject(autowiredBeanName))
+ {
+ if (_objectFactory.IsTypeMatch(autowiredBeanName, paramTypes[i]))
+ {
+ _cachedMethodArguments[i] =
+ new RuntimeObjectReference(autowiredBeanName);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ _cachedMethodArguments = null;
+ }
+ _cached = true;
+ }
+ }
+ }
+ if (arguments != null)
+ {
+ method.Invoke(target, arguments);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new ObjectCreationException("Could not autowire method: " + method, ex);
+ }
+ }
+
+ private Object[] ResolveCachedArguments(string objectName)
+ {
+ if (_cachedMethodArguments == null)
+ {
+ return null;
+ }
+ Object[] arguments = new Object[_cachedMethodArguments.Length];
+ for (int i = 0; i < arguments.Length; i++)
+ {
+ arguments[i] = ResolvedCachedArgument(objectName, _cachedMethodArguments[i]);
+ }
+ return arguments;
+ }
+ }
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/InjectionMetadata.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/InjectionMetadata.cs
new file mode 100644
index 00000000..1df4ffc9
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/InjectionMetadata.cs
@@ -0,0 +1,112 @@
+#region License
+
+/*
+ * Copyright © 2010-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Common.Logging;
+using Spring.Objects;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ ///
+ /// Internal class for managing injection metadata.
+ /// Not intended for direct use in applications.
+ ///
+ public class InjectionMetadata
+ {
+ private static readonly ILog Logger = LogManager.GetLogger();
+
+ private readonly IList _injectedElements;
+
+
+ ///
+ ///
+ ///
+ ///
+ public InjectionMetadata(Type targetType, IList elements)
+ {
+ _injectedElements = new List();
+ if (elements.Count > 0)
+ {
+ foreach (var element in elements)
+ {
+ Logger.Debug(m => m("Found injected element on class [" + targetType.Name + "]: " + element));
+ _injectedElements.Add(element);
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ public void CheckConfigMembers(RootObjectDefinition objectDefinition)
+ {
+ }
+
+
+ ///
+ /// Inject values for members into object instance
+ ///
+ ///
+ ///
+ ///
+ public void Inject(Object instance, string objectName, IPropertyValues pvs)
+ {
+ if (_injectedElements.Count == 0)
+ return;
+
+ foreach(var element in _injectedElements)
+ {
+ Logger.Debug(m => m("Processing injected method of bean '{0}': {1}", objectName, element));
+ element.Inject(instance, objectName, pvs);
+ }
+ }
+
+ ///
+ /// Represents an element that needs to be injected
+ ///
+ public abstract class InjectedElement
+ {
+ ///
+ /// The Property, field, method or constructor info
+ ///
+ protected readonly MemberInfo _member;
+
+ ///
+ /// Instantiates a new inject element
+ ///
+ ///
+ protected InjectedElement(MemberInfo member)
+ {
+ _member = member;
+ }
+
+ ///
+ /// Ececuted to inject value to associated memeber info
+ ///
+ ///
+ ///
+ ///
+ public abstract void Inject(object target, string requestingObjectName, IPropertyValues pvs);
+ }
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAttribute.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAttribute.cs
new file mode 100644
index 00000000..bf2e34ba
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAttribute.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ ///
+ /// This annotation may be used on a field or parameter as a qualifier for
+ /// candidate beans when autowiring. It may also be used to annotate other
+ /// custom annotations that can then in turn be used as qualifiers.
+ ///
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
+ public class QualifierAttribute : Attribute
+ {
+ private readonly string _name;
+
+ ///
+ /// Instantiate a new qualifier type
+ ///
+ /// name to use as qualifier
+ public QualifierAttribute(string name)
+ {
+ _name = name;
+ }
+
+ ///
+ /// Gets the name associated with this qualifier
+ ///
+ public string Name { get { return _name; } }
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/DependencyDescriptor.cs b/src/Spring/Spring.Core/Objects/Factory/Config/DependencyDescriptor.cs
index 39e8358c..cecbebe7 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/DependencyDescriptor.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/DependencyDescriptor.cs
@@ -20,6 +20,8 @@
using System;
using Spring.Core;
+using System.Reflection;
+using Spring.Objects.Factory.Attributes;
namespace Spring.Objects.Factory.Config
{
@@ -34,6 +36,10 @@ namespace Spring.Objects.Factory.Config
{
private MethodParameter methodParameter;
+ private PropertyInfo property;
+
+ private FieldInfo field;
+
private readonly bool required;
private readonly bool eager;
@@ -45,7 +51,8 @@ namespace Spring.Objects.Factory.Config
///
/// The MethodParameter to wrap.
/// if set to true if the dependency is required.
- public DependencyDescriptor(MethodParameter methodParameter, bool required) : this(methodParameter, required, true)
+ public DependencyDescriptor(MethodParameter methodParameter, bool required)
+ : this(methodParameter, required, true)
{
}
@@ -63,6 +70,55 @@ namespace Spring.Objects.Factory.Config
this.eager = eager;
}
+ ///
+ /// Create a new descriptor for a property.
+ /// Considers the dependency as 'eager'.
+ /// property to wrap
+ /// required whether the dependency is required
+ ///
+ public DependencyDescriptor(PropertyInfo property, bool required)
+ : this(property, required, true)
+ {
+ }
+
+ ///
+ /// Create a new descriptor for a property.
+ /// property to wrap
+ /// whether the dependency is required
+ /// whether this dependency is 'eager' in the sense of
+ /// eagerly resolving potential target beans for type matching
+ ///
+ public DependencyDescriptor(PropertyInfo property, bool required, bool eager)
+ {
+ this.property = property;
+ this.required = required;
+ this.eager = eager;
+ }
+
+ ///
+ /// Create a new descriptor for a field.
+ /// Considers the dependency as 'eager'.
+ /// field to wrap
+ /// whether the dependency is required
+ ///
+ public DependencyDescriptor(FieldInfo field, bool required)
+ : this(field, required, true)
+ {
+ }
+
+ ///
+ /// Create a new descriptor for a field.
+ /// field to wrap
+ /// whether the dependency is required
+ /// whether this dependency is 'eager' in the sense of
+ /// eagerly resolving potential target beans for type matching
+ ///
+ public DependencyDescriptor(FieldInfo field, bool required, bool eager)
+ {
+ this.field = field;
+ this.required = required;
+ this.eager = eager;
+ }
///
/// Gets a value indicating whether this dependency is required.
@@ -79,7 +135,17 @@ namespace Spring.Objects.Factory.Config
/// The type of the dependency (never null
public Type DependencyType
{
- get { return methodParameter.ParameterType; }
+ get
+ {
+ if (methodParameter != null)
+ return methodParameter.ParameterType;
+ if (property != null)
+ return property.PropertyType;
+ if (field != null)
+ return field.FieldType;
+
+ return null;
+ }
}
///
@@ -101,5 +167,83 @@ namespace Spring.Objects.Factory.Config
{
get { return methodParameter; }
}
+
+ public string Name
+ {
+ get
+ {
+ if (methodParameter != null)
+ return methodParameter.ParameterName();
+ if (property != null)
+ return property.Name;
+ if (field != null)
+ return field.Name;
+
+ return "";
+ }
+ }
+
+ ///
+ /// Determine whether the given dependency carries a value annotation.
+ ///
+ public Object GetSuggestedValue()
+ {
+ Object value = null;
+
+ if (methodParameter != null)
+ value = ConvertFieldName(methodParameter.ParameterName());
+ if (property != null)
+ value = property.Name;
+ if (field != null)
+ value = ConvertFieldName(field.Name);
+
+ return value;
+ }
+
+ ///
+ /// Get the qualifier name if exists
+ ///
+ public string GetQualifierName()
+ {
+ string value = null;
+
+ if (methodParameter != null)
+ value = FindValue(methodParameter.GetParameterAttributes());
+ if (property != null)
+ value = FindValue(Attribute.GetCustomAttributes(property));
+ if (field != null)
+ value = FindValue(Attribute.GetCustomAttributes(field));
+
+ return value;
+ }
+
+ /**
+ * Determine a suggested value from any of the given candidate annotations.
+ */
+
+ private string FindValue(Attribute[] attributesToSearch)
+ {
+ foreach (Attribute attribute in attributesToSearch)
+ {
+ if (attribute is QualifierAttribute)
+ {
+ var qualifierAttribute = attribute as QualifierAttribute;
+ return qualifierAttribute.Name;
+ }
+ }
+ return null;
+ }
+
+ private string ConvertFieldName(string fieldName)
+ {
+ if (string.IsNullOrEmpty(fieldName))
+ return string.Empty;
+
+ char[] letters = fieldName.TrimStart('_').ToCharArray();
+ letters[0] = char.ToUpper(letters[0]);
+
+ return new string(letters);
+ }
+
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs
index dbd12dea..f9b33de6 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs
@@ -1111,6 +1111,21 @@ namespace Spring.Objects.Factory.Support
public override object ResolveDependency(DependencyDescriptor descriptor, string objectName,
IList autowiredObjectNames)
{
+ string qualifierName = descriptor.GetQualifierName();
+ if (!string.IsNullOrEmpty(qualifierName))
+ {
+ if (ContainsObject(qualifierName))
+ {
+ autowiredObjectNames.Add(qualifierName);
+ return GetObject(qualifierName);
+ }
+ else
+ {
+ if (descriptor.Required)
+ throw new NoSuchObjectDefinitionException(qualifierName, "no object found with this name");
+ return null;
+ }
+ }
Type type = descriptor.DependencyType;
if (type.IsArray)
{
@@ -1133,6 +1148,38 @@ namespace Spring.Objects.Factory.Support
}
return TypeConversionUtils.ConvertValueIfNecessary(type, matchingObjects.Values, null);
}
+ else if (type.IsGenericType &&
+ (type.GetGenericTypeDefinition() == typeof(IList<>) || type.GetGenericTypeDefinition() == typeof(Spring.Collections.Generic.ISet<>) ||
+ type.GetGenericTypeDefinition() == typeof(IDictionary<,>)))
+ {
+ var isDictionary = (type.GetGenericTypeDefinition() == typeof (IDictionary<,>));
+ var elementType = isDictionary ? type.GetGenericArguments()[1] : type.GetGenericArguments()[0];
+
+ if (isDictionary && type.GetGenericArguments()[0] != typeof(string))
+ throw new NoSuchObjectDefinitionException(type,
+ "expected first generic to be a string but is " + type.GetGenericArguments()[0]);
+
+ IDictionary matchingObjects = FindAutowireCandidates(objectName, elementType, descriptor);
+ if (matchingObjects.Count == 0)
+ {
+ if (descriptor.Required)
+ {
+ RaiseNoSuchObjectDefinitionException(elementType, "dictionary/list/set of " + elementType.FullName, descriptor);
+ }
+ return null;
+ }
+ if (autowiredObjectNames != null)
+ {
+ foreach (DictionaryEntry matchingObject in matchingObjects)
+ {
+ autowiredObjectNames.Add(matchingObject.Key);
+ }
+ }
+
+ return isDictionary
+ ? TypeConversionUtils.ConvertValueIfNecessary(type, matchingObjects, null)
+ : TypeConversionUtils.ConvertValueIfNecessary(type, matchingObjects.Values, null);
+ }
else if (typeof(ICollection).IsAssignableFrom(type) && type.IsInterface)
{
//TODO - handle generic types.
@@ -1142,6 +1189,20 @@ namespace Spring.Objects.Factory.Support
else
{
IDictionary matchingObjects = FindAutowireCandidates(objectName, type, descriptor);
+ if (matchingObjects.Count == 0 || matchingObjects.Count > 1)
+ {
+ Object value = descriptor.GetSuggestedValue();
+ if (value is string)
+ {
+ string matchingObject = value as string;
+ if (ContainsObject(matchingObject))
+ {
+ matchingObjects.Clear();
+ matchingObjects.Add(matchingObject, GetObject(matchingObject));
+ }
+ }
+ }
+
if (matchingObjects.Count == 0)
{
if (descriptor.Required)
@@ -1155,9 +1216,8 @@ namespace Spring.Objects.Factory.Support
}
if (matchingObjects.Count > 1)
{
-
throw new NoSuchObjectDefinitionException(type,
- "expected single matching object but found " + matchingObjects.Count + ": " + matchingObjects);
+ "expected single matching object but found " + matchingObjects.Count + ": " + matchingObjects);
}
DictionaryEntry entry = (DictionaryEntry)ObjectUtils.EnumerateFirstElement(matchingObjects);
if (autowiredObjectNames != null)
@@ -1201,6 +1261,7 @@ namespace Spring.Objects.Factory.Support
}
}
}
+
for (int i = 0; i < candidateNames.Count; i++)
{
string candidateName = candidateNames[i];
diff --git a/src/Spring/Spring.Core/Spring.Core.2010.csproj b/src/Spring/Spring.Core/Spring.Core.2010.csproj
index 18b82f56..ced462ac 100644
--- a/src/Spring/Spring.Core/Spring.Core.2010.csproj
+++ b/src/Spring/Spring.Core/Spring.Core.2010.csproj
@@ -675,6 +675,10 @@
Code
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeCollectionTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeCollectionTests.cs
new file mode 100644
index 00000000..41a87e30
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeCollectionTests.cs
@@ -0,0 +1,160 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireAttributeCollectionTests
+ {
+ private GenericApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new GenericApplicationContext();
+
+ var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
+ objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
+ _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ColFoo1));
+ _applicationContext.RegisterObjectDefinition("Foo1", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ColFoo2));
+ _applicationContext.RegisterObjectDefinition("Foo2", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ColTestObject1));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("ColTestObject1", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ColTestObject2));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("ColTestObject2", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ColTestObject3));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("ColTestObject3", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ColTestObject4));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("ColTestObject4", objDef);
+
+ _applicationContext.Refresh();
+ }
+
+ [Test]
+ public void InjectAListOfObjects()
+ {
+ var testObj = (ColTestObject1)_applicationContext.GetObject("ColTestObject1");
+ var objDef = _applicationContext.ObjectFactory.GetObjectDefinition("ColTestObject1");
+
+ Assert.That(testObj.Count, Is.EqualTo(2));
+ Assert.That(objDef.DependsOn.Count, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void InjectASetOfObjects()
+ {
+ var testObj = (ColTestObject2)_applicationContext.GetObject("ColTestObject2");
+
+ Assert.That(testObj.Count, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void InjectADictionaryOfObjects()
+ {
+ var testObj = (ColTestObject3)_applicationContext.GetObject("ColTestObject3");
+
+ Assert.That(testObj.Count, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void InjectAnArrayOfObjects()
+ {
+ var testObj = (ColTestObject4)_applicationContext.GetObject("ColTestObject4");
+
+ Assert.That(testObj.Count, Is.EqualTo(2));
+ }
+ }
+
+ #region Test Objects
+
+ public interface IColFoo
+ {
+ string Name();
+ }
+
+ public class ColFoo1 : IColFoo
+ {
+ public string Name()
+ {
+ return "Foo1";
+ }
+ }
+
+ public class ColFoo2 : IColFoo
+ {
+ public string Name()
+ {
+ return "Foo2";
+ }
+ }
+
+ public class ColTestObject1
+ {
+ [Autowired]
+ private IList _col;
+
+ public int Count { get { return _col.Count; } }
+ }
+
+ public class ColTestObject2
+ {
+ [Autowired]
+ private Spring.Collections.Generic.ISet _col;
+
+ public int Count { get { return _col.Count; } }
+ }
+
+ public class ColTestObject3
+ {
+ [Autowired]
+ private IDictionary _col;
+
+ public int Count { get { return _col.Count; } }
+ }
+
+ public class ColTestObject4
+ {
+ [Autowired]
+ private IColFoo[] _col;
+
+ public int Count { get { return _col.Length; } }
+ }
+
+ #endregion
+
+}
\ No newline at end of file
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeConstructorTest.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeConstructorTest.cs
new file mode 100644
index 00000000..f745c501
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeConstructorTest.cs
@@ -0,0 +1,343 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireAttributeConstructorTest
+ {
+ private GenericApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new GenericApplicationContext();
+
+ var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
+ objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
+ _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsSimple));
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsSimple", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsAdvanced));
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsAdvanced", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsHello));
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsHello", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsCiao));
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsCiao", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsTestObject1));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject1", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsTestObject2));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject2", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsTestObject3));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject3", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsTestObject4));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject4", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsTestObject5));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject5", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsTestObject6));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject6", objDef);
+
+ objDef = new RootObjectDefinition(typeof(ConsTestObject7));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject7", objDef);
+
+ _applicationContext.Refresh();
+ }
+
+ [Test]
+ public void ConstructorWithInjectParameter()
+ {
+ var testObj = (ConsTestObject1)_applicationContext.GetObject("ConsTestObject1");
+
+ Assert.That(testObj.IsSet(), Is.True);
+ }
+
+ [Test]
+ public void SelectInjectConstructorOverDefault()
+ {
+ var testObj = (ConsTestObject2)_applicationContext.GetObject("ConsTestObject2");
+
+ Assert.That(testObj.IsSet(), Is.True);
+ }
+
+ [Test]
+ public void SelectConstructorWithMostParamters()
+ {
+ var testObj = (ConsTestObject3)_applicationContext.GetObject("ConsTestObject3");
+
+ Assert.That(testObj.IsSet(), Is.True);
+ }
+
+ [Test]
+ public void FailIfParameterAreRequired()
+ {
+ Exception ex = null;
+ try
+ {
+ var testObj = (ConsTestObject4)_applicationContext.GetObject("ConsTestObject4");
+ }
+ catch (Exception e) { ex = e; }
+
+ Assert.That(ex, Is.Not.Null, "Exception should be thrown");
+ Assert.That(ex.Message, Is.StringContaining("Unsatisfied dependency expressed"));
+ }
+
+ [Test]
+ public void InjectCollection()
+ {
+ var testObj = (ConsTestObject5)_applicationContext.GetObject("ConsTestObject5");
+
+ Assert.That(testObj.IsSet(), Is.True);
+ Assert.That(testObj.ObjectCount(), Is.EqualTo(2));
+ }
+
+
+ [Test]
+ public void SetParameterByParameterName()
+ {
+ var testObj = (ConsTestObject6)_applicationContext.GetObject("ConsTestObject6");
+
+ Assert.That(testObj.IsSet(), Is.True);
+ }
+
+ [Test]
+ public void SetParameterByQualifier()
+ {
+ var testObj = (ConsTestObject7)_applicationContext.GetObject("ConsTestObject7");
+
+ Assert.That(testObj.IsSet(), Is.True);
+ Assert.That(testObj.CorrectObject(), Is.True);
+ }
+ }
+
+ #region Test Objects
+
+ public interface IConsSimple
+ {
+ string Message();
+ }
+
+ public class ConsSimple : IConsSimple
+ {
+ public string Message()
+ {
+ return "ok";
+ }
+ }
+
+ public interface IConsAdvanced
+ {
+ string Message();
+ }
+
+ public class ConsAdvanced : IConsAdvanced
+ {
+ public string Message()
+ {
+ return "ok";
+ }
+ }
+
+ public interface INotSet
+ {
+ }
+
+ public interface IConsCol
+ {
+ string Message();
+ }
+
+ public class ConsHello : IConsCol
+ {
+ public string Message()
+ {
+ return "hello";
+ }
+ }
+
+ public class ConsCiao : IConsCol
+ {
+ public string Message()
+ {
+ return "ciao";
+ }
+ }
+
+ public class ConsTestObject1
+ {
+ private IConsSimple _consSimple;
+
+ [Autowired]
+ public ConsTestObject1(IConsSimple consSimple)
+ {
+ _consSimple = consSimple;
+ }
+
+ public bool IsSet()
+ {
+ return _consSimple != null;
+ }
+ }
+
+ public class ConsTestObject2
+ {
+ private IConsSimple _consSimple;
+
+ public ConsTestObject2()
+ {
+ }
+
+ [Autowired]
+ public ConsTestObject2(IConsSimple consSimple)
+ {
+ _consSimple = consSimple;
+ }
+
+ public bool IsSet()
+ {
+ return _consSimple != null;
+ }
+ }
+
+ public class ConsTestObject3
+ {
+ private IConsSimple _consSimple;
+ private IConsAdvanced _consAdvanced;
+
+ [Autowired(Required = false)]
+ public ConsTestObject3(IConsSimple consSimple)
+ {
+ _consSimple = consSimple;
+ }
+
+ [Autowired(Required = false)]
+ public ConsTestObject3(IConsSimple consSimple, IConsAdvanced consAdvanced)
+ {
+ _consSimple = consSimple;
+ _consAdvanced = consAdvanced;
+ }
+
+ public bool IsSet()
+ {
+ return _consSimple != null && _consAdvanced != null;
+ }
+ }
+
+ public class ConsTestObject4
+ {
+ private INotSet _notSet;
+
+ [Autowired]
+ public ConsTestObject4(INotSet notSet)
+ {
+ _notSet = notSet;
+ }
+
+ public bool IsSet()
+ {
+ return _notSet != null;
+ }
+ }
+
+ public class ConsTestObject5
+ {
+ private IDictionary _consCol;
+
+ [Autowired]
+ public ConsTestObject5(IDictionary consCol)
+ {
+ _consCol = consCol;
+ }
+
+ public bool IsSet()
+ {
+ return _consCol != null;
+ }
+
+ public int ObjectCount()
+ {
+ return _consCol.Count;
+ }
+ }
+
+ public class ConsTestObject6
+ {
+ private IConsCol _consHello;
+
+ [Autowired]
+ public ConsTestObject6(IConsCol consHello)
+ {
+ _consHello = consHello;
+ }
+
+ public bool IsSet()
+ {
+ return _consHello != null;
+ }
+ }
+
+ public class ConsTestObject7
+ {
+ private IConsCol _consHello;
+
+ [Autowired]
+ public ConsTestObject7([Qualifier("ConsCiao")] IConsCol consHello)
+ {
+ _consHello = consHello;
+ }
+
+ public bool IsSet()
+ {
+ return _consHello != null;
+ }
+
+ public bool CorrectObject()
+ {
+ return _consHello.Message() == "ciao";
+ }
+ }
+
+ #endregion
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeFieldTest.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeFieldTest.cs
new file mode 100644
index 00000000..b9fc2c29
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeFieldTest.cs
@@ -0,0 +1,290 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireAttributeFieldTest
+ {
+ private GenericApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new GenericApplicationContext();
+
+ var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
+ objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
+ _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
+
+
+ objDef = new RootObjectDefinition(typeof(FldFooImpl));
+ _applicationContext.RegisterObjectDefinition("FldFoo", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldHello));
+ _applicationContext.RegisterObjectDefinition("FldHello", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldCioa));
+ _applicationContext.RegisterObjectDefinition("FldCioa", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldHola));
+ _applicationContext.RegisterObjectDefinition("FldHola", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldTestObject1));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("FldTestObject1", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldTestObject2));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("FldTestObject2", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldTestObject3));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("FldTestObject3", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldTestObject4));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("FldTestObject4", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldTestObject5));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("FldTestObject5", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldTestObject6));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("FldTestObject6", objDef);
+
+ objDef = new RootObjectDefinition(typeof(FldTestObject7));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("FldTestObject7", objDef);
+
+ _applicationContext.Refresh();
+ }
+
+ [Test]
+ public void InjectPropertyBasedOnFieldType()
+ {
+ var testObj = (FldTestObject1)_applicationContext.GetObject("FldTestObject1");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("FldTestObject1");
+
+ Assert.That(testObj.Test(), Is.EqualTo("foo"));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void WithTwoTypesRegisteredAndNoNameShouldFail()
+ {
+ Assert.That(delegate { var testObj = (FldTestObject2)_applicationContext.GetObject("FldTestObject2"); }, Throws.Exception.TypeOf());
+ }
+
+ [Test]
+ public void WithQualifierName()
+ {
+ var testObj = (FldTestObject3)_applicationContext.GetObject("FldTestObject3");
+
+ Assert.That(testObj.Say(), Is.EqualTo("cioa"));
+ }
+
+ [Test]
+ public void WithTwoTypesAndNoQualifierUsePopertyName()
+ {
+ var testObj = (FldTestObject4)_applicationContext.GetObject("FldTestObject4");
+
+ Assert.That(testObj.Say(), Is.EqualTo("cioa"));
+ }
+
+ [Test]
+ public void FailIfTypeCantBeResolved()
+ {
+ Exception ex = null;
+ try
+ {
+ var testObj = (FldTestObject5)_applicationContext.GetObject("FldTestObject5");
+ }
+ catch (Exception e) { ex = e; }
+
+ Assert.That(ex, Is.Not.Null, "Should throw an exception");
+ Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
+ }
+
+ [Test]
+ public void InjectedObjectAssignedToTwoInterfaces()
+ {
+ var testObj = (FldTestObject6)_applicationContext.GetObject("FldTestObject6");
+
+ Assert.That(testObj.Test(), Is.EqualTo("test"));
+ }
+
+ [Test]
+ public void IsNotRequired()
+ {
+ var testObj = (FldTestObject7)_applicationContext.GetObject("FldTestObject7");
+
+ Assert.That(testObj.IsNull(), Is.True);
+ }
+
+ }
+
+
+ #region Test Objects
+
+ public interface IFldNotAnObject
+ {
+
+ }
+
+ public interface IFldAnotherOne
+ {
+ string Quite();
+ }
+
+ public interface IFldFoo
+ {
+ string Test();
+ }
+
+ public class FldFooImpl : IFldFoo
+ {
+ public string Test()
+ {
+ return "foo";
+ }
+ }
+
+ public interface IFldSay
+ {
+ string Say();
+ }
+
+ public class FldHello : IFldSay
+ {
+ public string Say()
+ {
+ return "hello";
+ }
+ }
+
+ public class FldCioa : IFldSay
+ {
+ public string Say()
+ {
+ return "cioa";
+ }
+ }
+
+ public class FldHola : IFldFoo, IFldAnotherOne
+ {
+ public string Quite()
+ {
+ return "test";
+ }
+
+ public string Test()
+ {
+ return "test";
+ }
+ }
+
+ public class FldTestObject1
+ {
+ [Autowired]
+ private IFldFoo _fldFoo;
+
+ public string Test()
+ {
+ return _fldFoo.Test();
+ }
+ }
+
+ // object with 2 possibilities should fail
+ public class FldTestObject2
+ {
+ [Autowired]
+ private IFldSay _wrongName;
+
+ public string Say()
+ {
+ return _wrongName.Say();
+ }
+ }
+
+ // should not fail but inject Cioa object
+ public class FldTestObject3
+ {
+ [Autowired]
+ [Qualifier("FldCioa")]
+ private IFldSay _fldCioa;
+
+ public string Say()
+ {
+ return _fldCioa.Say();
+ }
+ }
+
+ // should not fail but inject Hello via Propertyname
+ public class FldTestObject4
+ {
+ [Autowired]
+ private IFldSay _fldCioa;
+
+ public string Say()
+ {
+ return _fldCioa.Say();
+ }
+ }
+
+ // should not fail but inject Hello via Propertyname
+ public class FldTestObject5
+ {
+ [Autowired]
+ private IFldNotAnObject _ohhh;
+ }
+
+ public class FldTestObject6
+ {
+ [Autowired]
+ private IFldAnotherOne _hola;
+
+ public string Test()
+ {
+ return _hola.Quite();
+ }
+ }
+
+ public class FldTestObject7
+ {
+ [Autowired(Required = false)]
+ private IFldNotAnObject _nono;
+
+ public bool IsNull()
+ {
+ return (_nono == null);
+ }
+ }
+
+ #endregion
+
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeMethodsTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeMethodsTests.cs
new file mode 100644
index 00000000..8d0bd0b5
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeMethodsTests.cs
@@ -0,0 +1,371 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireAttributeMethodsTests
+ {
+ private GenericApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new GenericApplicationContext();
+
+ var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
+ objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
+ _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
+
+ objDef = new RootObjectDefinition(typeof(Simple));
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("Simple", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodHello));
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodHello", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodCiao));
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodCiao", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject1));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject1", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject2));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject2", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject3));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject3", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject4));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject4", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject5));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject5", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject6));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject6", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject7));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject7", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject8));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject8", objDef);
+
+ objDef = new RootObjectDefinition(typeof(MethodTestObject9));
+ objDef.Scope = "prototype";
+ _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject9", objDef);
+
+ _applicationContext.Refresh();
+ }
+
+ [Test]
+ public void InObjectByType()
+ {
+ var testObj = (MethodTestObject1)_applicationContext.GetObject("MethodTestObject1");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("MethodTestObject1");
+
+ Assert.That(testObj.GetObject(), Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectByParamterName()
+ {
+ var testObj = (MethodTestObject2)_applicationContext.GetObject("MethodTestObject2");
+
+ Assert.That(testObj.GetObject(), Is.Not.Null);
+ }
+
+ [Test]
+ public void InjectByQualifier()
+ {
+ var testObj = (MethodTestObject3)_applicationContext.GetObject("MethodTestObject3");
+
+ Assert.That(testObj.GetObject(), Is.Not.Null);
+ }
+
+ [Test]
+ public void FailIfTypeCantBeResolved()
+ {
+ Exception ex = null;
+ try
+ {
+ var testObj = (FldTestObject5)_applicationContext.GetObject("MethodTestObject4");
+ }
+ catch (Exception e) { ex = e; }
+
+ Assert.That(ex, Is.Not.Null, "Should throw an exception");
+ Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
+ }
+
+ [Test]
+ public void InjectListOfObjects()
+ {
+ var testObj = (MethodTestObject5)_applicationContext.GetObject("MethodTestObject5");
+
+ Assert.That(testObj.GetObject(), Is.Not.Null);
+ Assert.That(testObj.GetObject().Count, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void InjectSeveralParameters()
+ {
+ var testObj = (MethodTestObject6)_applicationContext.GetObject("MethodTestObject6");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("MethodTestObject6");
+
+ Assert.That(testObj.GetObject(), Is.Not.Null);
+ Assert.That(testObj.GetSimple(), Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void FailIfObjecNotAvailable()
+ {
+ Assert.That(delegate { var testObj = (MethodTestObject7)_applicationContext.GetObject("MethodTestObject7"); },
+ Throws.Exception.TypeOf());
+ }
+
+ [Test]
+ public void PassIfObjectNotavailableButNotRequired()
+ {
+ var testObj1 = (MethodTestObject8)_applicationContext.GetObject("MethodTestObject8");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("MethodTestObject8");
+
+ Assert.That(testObj1.GetSimple(), Is.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+
+ var testObj2 = (MethodTestObject9)_applicationContext.GetObject("MethodTestObject9");
+ objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("MethodTestObject9");
+
+ Assert.That(testObj2.GetrAdvanced(), Is.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+
+ }
+
+
+ #region Test Objects
+
+ public interface ISimple
+ {
+ string Foo();
+ }
+
+ public class Simple : ISimple
+ {
+ public string Foo()
+ {
+ return "simple";
+ }
+ }
+
+ public interface IAdvanced
+ {
+
+ }
+
+ public interface IMethodFoo
+ {
+ string Foo();
+ }
+
+ public class MethodHello : IMethodFoo
+ {
+ public string Foo()
+ {
+ return "hello";
+ }
+ }
+
+ public class MethodCiao : IMethodFoo
+ {
+ public string Foo()
+ {
+ return "ciao";
+ }
+ }
+
+ public class MethodTestObject1
+ {
+ private ISimple _impl;
+
+ [Autowired]
+ public void Prepare(ISimple impl)
+ {
+ _impl = impl;
+ }
+
+ public object GetObject()
+ {
+ return _impl;
+ }
+ }
+
+ public class MethodTestObject2
+ {
+ private IMethodFoo _methodCiao;
+
+ [Autowired]
+ public void Prepare(IMethodFoo methodCiao)
+ {
+ _methodCiao = methodCiao;
+ }
+
+ public object GetObject()
+ {
+ return _methodCiao;
+ }
+ }
+
+ public class MethodTestObject3
+ {
+ private IMethodFoo _impl;
+
+ [Autowired]
+ public void Prepare([Qualifier("MethodHello")] IMethodFoo impl)
+ {
+ _impl = impl;
+ }
+
+ public object GetObject()
+ {
+ return _impl;
+ }
+ }
+
+ public class MethodTestObject4
+ {
+ private IMethodFoo _impl;
+
+ [Autowired]
+ public void Prepare([Qualifier("MethodHello")] IMethodFoo impl, string test)
+ {
+ _impl = impl;
+ }
+
+ public object GetObject()
+ {
+ return _impl;
+ }
+ }
+
+ public class MethodTestObject5
+ {
+ private IList _impl;
+
+ [Autowired]
+ public void Prepare(IList impl)
+ {
+ _impl = impl;
+ }
+
+ public IList GetObject()
+ {
+ return _impl;
+ }
+ }
+
+ public class MethodTestObject6
+ {
+ private IMethodFoo _impl;
+ private ISimple _simple;
+
+ [Autowired]
+ public void Prepare(IMethodFoo methodHello, ISimple simple)
+ {
+ _impl = methodHello;
+ _simple = simple;
+ }
+
+ public object GetObject()
+ {
+ return _impl;
+ }
+
+ public object GetSimple()
+ {
+ return _simple;
+ }
+ }
+
+ public class MethodTestObject7
+ {
+ private ISimple _simple;
+
+ [Autowired]
+ public void Prepare([Qualifier("NotAvailable")] ISimple simple)
+ {
+ _simple = simple;
+ }
+
+ public object GetSimple()
+ {
+ return _simple;
+ }
+ }
+
+ public class MethodTestObject8
+ {
+ private ISimple _simple;
+
+ [Autowired(Required = false)]
+ public void Prepare([Qualifier("NotAvailable")] ISimple simple)
+ {
+ _simple = simple;
+ }
+
+ public object GetSimple()
+ {
+ return _simple;
+ }
+ }
+
+ public class MethodTestObject9
+ {
+ private IAdvanced _advanced;
+
+ [Autowired(Required = false)]
+ public void Prepare(IAdvanced advanced)
+ {
+ _advanced = advanced;
+ }
+
+ public object GetrAdvanced()
+ {
+ return _advanced;
+ }
+ }
+
+ #endregion
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributePropertyTest.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributePropertyTest.cs
new file mode 100644
index 00000000..eec2e459
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributePropertyTest.cs
@@ -0,0 +1,254 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireAttributePropertyTest
+ {
+ private GenericApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new GenericApplicationContext();
+
+ var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
+ objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
+ _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
+
+
+ objDef = new RootObjectDefinition(typeof(PropFooImpl));
+ _applicationContext.RegisterObjectDefinition("PropFoo", objDef);
+
+ objDef = new RootObjectDefinition(typeof(PropHello));
+ _applicationContext.RegisterObjectDefinition("PropHello", objDef);
+
+ objDef = new RootObjectDefinition(typeof(PropCioa));
+ _applicationContext.RegisterObjectDefinition("PropCioa", objDef);
+
+ objDef = new RootObjectDefinition(typeof(PropTestObject1));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("PropTestObject1", objDef);
+
+ objDef = new RootObjectDefinition(typeof(PropTestObject2));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("PropTestObject2", objDef);
+
+ objDef = new RootObjectDefinition(typeof(PropTestObject3));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("PropTestObject3", objDef);
+
+ objDef = new RootObjectDefinition(typeof(PropTestObject4));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("PropTestObject4", objDef);
+
+ objDef = new RootObjectDefinition(typeof(PropTestObject5));
+ objDef.Scope = "prototype";
+ _applicationContext.RegisterObjectDefinition("PropTestObject5", objDef);
+
+ _applicationContext.Refresh();
+ }
+
+ [Test]
+ public void InjectPropertyBasedOnPropertyType()
+ {
+ var testObj = (PropTestObject1)_applicationContext.GetObject("PropTestObject1");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("PropTestObject1");
+
+ Assert.That(testObj.Foo, Is.Not.Null);
+ Assert.That(testObj.Test(), Is.EqualTo("foo"));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1), "Should have one Dependant Object");
+ }
+
+ [Test]
+ public void WithTwoTypesRegisteredAndNoNameShouldFail()
+ {
+ Assert.That(delegate { var testObj = (PropTestObject2)_applicationContext.GetObject("PropTestObject2"); }, Throws.Exception.TypeOf());
+ }
+
+ [Test]
+ public void WithQualifierName()
+ {
+ var testObj = (PropTestObject3)_applicationContext.GetObject("PropTestObject3");
+
+ Assert.That(testObj.Cioa, Is.Not.Null);
+ Assert.That(testObj.Say(), Is.EqualTo("cioa"));
+ }
+
+ [Test]
+ public void WithTwoTypesAndNoQualifierUsePopertyName()
+ {
+ var testObj = (PropTestObject4)_applicationContext.GetObject("PropTestObject4");
+
+ Assert.That(testObj.PropCioa, Is.Not.Null);
+ Assert.That(testObj.Say(), Is.EqualTo("cioa"));
+ }
+
+ [Test]
+ public void FailIfTypeCantBeResolved()
+ {
+ Exception ex = null;
+ try
+ {
+ var testObj = (FldTestObject5)_applicationContext.GetObject("PropTestObject5");
+ }
+ catch (Exception e) { ex = e; }
+
+ Assert.That(ex, Is.Not.Null, "Should throw an exception");
+ Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
+ }
+
+ }
+
+ #region Test Objects
+
+ public interface IPropNotAnObject
+ {
+
+ }
+
+ public interface IPropFoo
+ {
+ string Test();
+ }
+
+ public class PropFooImpl : IPropFoo
+ {
+ public string Test()
+ {
+ return "foo";
+ }
+ }
+
+ public interface IPropSay
+ {
+ string PropSay();
+ }
+
+ public class PropHello : IPropSay
+ {
+ public string PropSay()
+ {
+ return "hello";
+ }
+ }
+
+ public class PropCioa : IPropSay
+ {
+ public string PropSay()
+ {
+ return "cioa";
+ }
+ }
+
+ public class PropTestObject1
+ {
+ private IPropFoo _foo;
+
+ [Autowired]
+ public IPropFoo Foo
+ {
+ get { return _foo; }
+ set { _foo = value; }
+ }
+
+ public string Test()
+ {
+ return _foo.Test();
+ }
+ }
+
+ public class PropTestObject2
+ {
+ private IPropSay _hello;
+
+ [Autowired]
+ public IPropSay WrongName
+ {
+ get { return _hello; }
+ set { _hello = value; }
+ }
+
+ public string Say()
+ {
+ return _hello.PropSay();
+ }
+ }
+
+ // should not fail but inject Cioa object
+ public class PropTestObject3
+ {
+ private IPropSay _cioa;
+
+ [Autowired]
+ [Qualifier("PropCioa")]
+ public IPropSay Cioa
+ {
+ get { return _cioa; }
+ set { _cioa = value; }
+ }
+
+ public string Say()
+ {
+ return _cioa.PropSay();
+ }
+ }
+
+ // should not fail but inject Hello via Propertyname
+ public class PropTestObject4
+ {
+ private IPropSay _obj;
+
+ [Autowired]
+ public IPropSay PropCioa
+ {
+ get { return _obj; }
+ set { _obj = value; }
+ }
+
+ public string Say()
+ {
+ return _obj.PropSay();
+ }
+ }
+
+ // should not fail but inject Hello via Propertyname
+ public class PropTestObject5
+ {
+ private IPropNotAnObject _obj;
+
+ [Autowired]
+ public IPropNotAnObject Ohhh
+ {
+ get { return _obj; }
+ set { _obj = value; }
+ }
+ }
+
+ #endregion
+
+}
diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj
index d9fbeafe..66411318 100644
--- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj
+++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj
@@ -318,6 +318,11 @@
+
+
+
+
+
From dc386ecd7bd2e375dfe51cf1a601538c16b9f407 Mon Sep 17 00:00:00 2001
From: Thomas Trageser
Date: Sat, 1 Sep 2012 18:52:51 +0100
Subject: [PATCH 2/6] Add AutowireAttributePostProcessor for attribute driven
auto wiring, fine grained control via QualifierAttribute or ValueAttribute
(Expressions, PropertyPlaceHolder). Updated XML configuration to support
primary attribute. Also added possibility to add a Qualifier and Meta element
to define an object for QualifierAttribute.
---
.../Core/AttributeAccessorSupport.cs | 110 ++++
.../Spring.Core/Core/IAttributeAccessor.cs | 77 +++
.../Spring.Core/Core/MethodParameter.cs | 32 +-
.../AutowiredAttributeObjectPostProcessor.cs | 106 ++--
...fierAnnotationAutowireCandidateResolver.cs | 295 +++++++++
.../Factory/Attributes/QualifierAttribute.cs | 44 +-
.../Factory/Attributes/ValueAttribute.cs | 37 ++
.../Factory/Config/DependencyDescriptor.cs | 86 +--
.../Config/IConfigurableObjectFactory.cs | 13 +
.../Factory/Config/IObjectDefinition.cs | 7 +
.../Factory/Config/ObjectDefinitionHolder.cs | 11 +
.../Config/PropertyPlaceholderConfigurer.cs | 10 +-
.../Support/AbstractObjectDefinition.cs | 78 ++-
.../Factory/Support/AbstractObjectFactory.cs | 29 +
.../Support/AutowireCandidateQualifier.cs | 102 +++
.../Objects/Factory/Support/AutowireUtils.cs | 3 +-
.../Support/DefaultListableObjectFactory.cs | 134 ++--
.../Support/IAutowireCandidateResolver.cs | 12 +
.../SimpleAutowireCandidateResolver.cs | 13 +
.../Factory/Xml/ObjectDefinitionConstants.cs | 20 +
.../Factory/Xml/ObjectsNamespaceParser.cs | 80 ++-
.../Factory/Xml/spring-objects-2.0.xsd | 595 ++++++++++++++++++
.../Factory/Xml/spring-objects-2.0.xsx | 88 +++
.../Objects/IObjectMetadataElement.cs | 37 ++
.../Objects/ObjectMetadataAttribute.cs | 95 +++
.../ObjectMetadataAttributeAccessor.cs | 83 +++
.../Spring.Core/Spring.Core.2008.csproj | 14 +
.../Spring.Core/Spring.Core.2010.csproj | 12 +
src/Spring/Spring.Core/Spring.Core.build | 1 +
src/Spring/Spring.Core/Util/AttributeUtils.cs | 42 ++
.../Spring.Core/Util/IStringValueResolver.cs | 20 +
src/Spring/Spring.Core/Util/ObjectUtils.cs | 13 +
.../AutowireAttributeCollectionTests.cs | 160 -----
.../AutowireAttributeConstructorTest.cs | 343 ----------
.../Attributes/AutowireAttributeFieldTest.cs | 290 ---------
.../AutowireAttributeMethodsTests.cs | 371 -----------
.../AutowireAttributePropertyTest.cs | 254 --------
.../AutowireByQualifierAttributeTests.cs | 87 +++
.../Attributes/AutowireByQualifierTests.cs | 87 +++
.../Attributes/AutowireByTypeFailTests.cs | 98 +++
.../Attributes/AutowireByTypeNormalTests.cs | 82 +++
.../AutowireByTypeNotRequiredTests.cs | 72 +++
.../Attributes/AutowireByTypePrimaryTests.cs | 82 +++
.../Attributes/AutowireByValueTests.cs | 96 +++
.../Attributes/AutowireCollectionTests.cs | 106 ++++
.../Factory/Attributes/AutowireTestObjects.cs | 252 ++++++++
.../ByQualifierAttributeObjects.xml | 36 ++
.../Factory/Attributes/ByQualifierObjects.xml | 32 +
.../Factory/Attributes/ByTypeFailObjects.xml | 28 +
.../Attributes/ByTypeNormalObjects.xml | 25 +
.../Attributes/ByTypeNotRequiredObjects.xml | 18 +
.../Attributes/ByTypePrimaryObjects.xml | 29 +
.../Factory/Attributes/ByValueObjects.config | 15 +
.../Factory/Attributes/ByValueObjects.xml | 37 ++
.../Factory/Attributes/CollectionObjects.xml | 36 ++
.../PropertyPlaceholderConfigurerTests.cs | 4 +
...supportedObjectDefinitionImplementation.cs | 5 +
.../Spring.Core.Tests.2008.csproj | 32 +-
.../Spring.Core.Tests.2010.csproj | 23 +-
.../Spring.Core.Tests/Spring.Core.Tests.build | 1 +
60 files changed, 3414 insertions(+), 1586 deletions(-)
create mode 100644 src/Spring/Spring.Core/Core/AttributeAccessorSupport.cs
create mode 100644 src/Spring/Spring.Core/Core/IAttributeAccessor.cs
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAnnotationAutowireCandidateResolver.cs
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Attributes/ValueAttribute.cs
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Support/AutowireCandidateQualifier.cs
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-2.0.xsd
create mode 100644 src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-2.0.xsx
create mode 100644 src/Spring/Spring.Core/Objects/IObjectMetadataElement.cs
create mode 100644 src/Spring/Spring.Core/Objects/ObjectMetadataAttribute.cs
create mode 100644 src/Spring/Spring.Core/Objects/ObjectMetadataAttributeAccessor.cs
create mode 100644 src/Spring/Spring.Core/Util/IStringValueResolver.cs
delete mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeCollectionTests.cs
delete mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeConstructorTest.cs
delete mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeFieldTest.cs
delete mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeMethodsTests.cs
delete mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributePropertyTest.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByQualifierAttributeTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByQualifierTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeFailTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeNormalTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeNotRequiredTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypePrimaryTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByValueTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireCollectionTests.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireTestObjects.cs
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByQualifierAttributeObjects.xml
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByQualifierObjects.xml
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeFailObjects.xml
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeNormalObjects.xml
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeNotRequiredObjects.xml
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypePrimaryObjects.xml
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByValueObjects.config
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByValueObjects.xml
create mode 100644 test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/CollectionObjects.xml
diff --git a/src/Spring/Spring.Core/Core/AttributeAccessorSupport.cs b/src/Spring/Spring.Core/Core/AttributeAccessorSupport.cs
new file mode 100644
index 00000000..623798ee
--- /dev/null
+++ b/src/Spring/Spring.Core/Core/AttributeAccessorSupport.cs
@@ -0,0 +1,110 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+namespace Spring.Core
+{
+ ///
+ /// Support class for , providing
+ /// a base implementation of all methods. To be extended by subclasses.
+ ///
+ [Serializable]
+ public abstract class AttributeAccessorSupport : IAttributeAccessor
+ {
+ /** Map with String keys and Object values */
+ private readonly IDictionary _attributes = new Dictionary();
+
+
+ public virtual void SetAttribute(string name, object value)
+ {
+ Trace.Assert(name != null, "Name must not be null");
+ if (value != null) {
+ _attributes.Add(name, value);
+ }
+ else {
+ RemoveAttribute(name);
+ }
+ }
+
+ public virtual object GetAttribute(string name)
+ {
+ Trace.Assert(name != null, "Name must not be null");
+ if (_attributes.ContainsKey(name))
+ return _attributes[name];
+ return null;
+ }
+
+ public virtual object RemoveAttribute(string name) {
+ Trace.Assert(name != null, "Name must not be null");
+ if (_attributes.ContainsKey(name))
+ return _attributes.Remove(name);
+ return false;
+ }
+
+ public bool HasAttribute(string name)
+ {
+ Trace.Assert(name != null, "Name must not be null");
+ return _attributes.ContainsKey(name);
+ }
+
+ public String[] AttributeNames
+ {
+ get
+ {
+ return _attributes.Keys.ToArray();
+ }
+ }
+
+
+ /**
+ * Copy the attributes from the supplied AttributeAccessor to this accessor.
+ * @param source the AttributeAccessor to copy from
+ */
+ protected void CopyAttributesFrom(IAttributeAccessor source) {
+ Trace.Assert(source != null, "Source must not be null");
+ string[] attributeNames = source.AttributeNames;
+ foreach(string attributeName in attributeNames)
+ {
+ SetAttribute(attributeName, source.GetAttribute(attributeName));
+ }
+ }
+
+
+ public override bool Equals(object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other is AttributeAccessorSupport)) {
+ return false;
+ }
+ var that = (AttributeAccessorSupport) other;
+ return _attributes.Equals(that._attributes);
+ }
+
+ public override int GetHashCode()
+ {
+ return _attributes.GetHashCode();
+ }
+ }
+}
diff --git a/src/Spring/Spring.Core/Core/IAttributeAccessor.cs b/src/Spring/Spring.Core/Core/IAttributeAccessor.cs
new file mode 100644
index 00000000..e849e1cf
--- /dev/null
+++ b/src/Spring/Spring.Core/Core/IAttributeAccessor.cs
@@ -0,0 +1,77 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Spring.Core
+{
+ ///
+ /// Interface defining a generic contract for attaching and accessing metadata
+ /// to/from arbitrary objects.
+ ///
+ public interface IAttributeAccessor
+ {
+ ///
+ /// Set the attribute defined by name to the supplied value.
+ /// If value is null, the attribute is {@link #removeAttribute removed}.
+ // In general, users should take care to prevent overlaps with other
+ /// metadata attributes by using fully-qualified names, perhaps using
+ /// class or package names as prefix.
+ ///
+ /// the unique attribute key
+ /// the attribute value to be attached
+ void SetAttribute(string name, object value);
+
+ ///
+ /// Get the value of the attribute identified by name.
+ /// Return null if the attribute doesn't exist.
+ ///
+ /// the unique attribute key
+ /// the current value of the attribute, if any
+ object GetAttribute(string name);
+
+ ///
+ /// Remove the attribute identified by name and return its value.
+ /// Return null if no attribute under name is found.
+ ///
+ /// the unique attribute key
+ /// The last value of the attribute, if any
+ object RemoveAttribute(string name);
+
+ ///
+ /// Checks weather a specific attributes exists
+ ///
+ /// The unique attribute key
+ ///
+ /// true if the attribute identified by name exists.
+ /// Otherwise return false
+ ///
+ bool HasAttribute(string name);
+
+ ///
+ /// Return the names of all attributes.
+ ///
+ String[] AttributeNames { get; }
+
+ }
+}
diff --git a/src/Spring/Spring.Core/Core/MethodParameter.cs b/src/Spring/Spring.Core/Core/MethodParameter.cs
index 1a923378..7d5c8f5c 100644
--- a/src/Spring/Spring.Core/Core/MethodParameter.cs
+++ b/src/Spring/Spring.Core/Core/MethodParameter.cs
@@ -39,6 +39,7 @@ namespace Spring.Core
private ConstructorInfo constructorInfo;
private readonly int parameterIndex;
+
private Type parameterType;
///
@@ -137,12 +138,33 @@ namespace Spring.Core
get { return constructorInfo; }
}
- public Attribute[] GetParameterAttributes()
+ ///
+ /// Return the annotations associated with the specific method/constructor parameter.
+ ///
+ public Attribute[] ParameterAttributes
{
- if (methodInfo != null)
- return Attribute.GetCustomAttributes(methodInfo.GetParameters()[parameterIndex]);
- else
- return Attribute.GetCustomAttributes(constructorInfo.GetParameters()[parameterIndex]);
+ get
+ {
+ if (methodInfo != null)
+ return Attribute.GetCustomAttributes(methodInfo.GetParameters()[parameterIndex]);
+ else
+ return Attribute.GetCustomAttributes(constructorInfo.GetParameters()[parameterIndex]);
+ }
}
+
+ ///
+ /// Return the annotations associated with the target method/constructor itself.
+ ///
+ public Attribute[] MethodAttributes
+ {
+ get
+ {
+ if (methodInfo != null)
+ return Attribute.GetCustomAttributes(methodInfo);
+ else
+ return Attribute.GetCustomAttributes(constructorInfo);
+ }
+ }
+
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs
index 07c74ea8..38ad3593 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs
@@ -79,7 +79,7 @@ namespace Spring.Objects.Factory.Attributes
private readonly IDictionary _injectionMetadataCache =
new Dictionary();
- private Type _autowiredPropertyType = typeof (AutowiredAttribute);
+ private IList _autowiredPropertyTypes = new List();
///
/// Return the order value of this object, where a higher value means greater in
@@ -125,16 +125,25 @@ namespace Spring.Objects.Factory.Attributes
set { _objectFactory = (IConfigurableListableObjectFactory) value; }
}
-
///
- /// Sets the used AutowiredAttributeType during the scan
+ /// Add a Autowired Attribute Type
///
- public Type AutowiredAttributeType
+ public void AddAutowiredType(Type attributeType)
{
- get { return _autowiredPropertyType; }
- set { _autowiredPropertyType = value; }
+ if (!_autowiredPropertyTypes.Contains(attributeType))
+ _autowiredPropertyTypes.Add(attributeType);
}
+ ///
+ /// Create a new instance of an Autowire Post Processor
+ /// with standard attributes of
+ /// and
+ ///
+ public AutowiredAttributeObjectPostProcessor()
+ {
+ _autowiredPropertyTypes.Add(typeof(AutowiredAttribute));
+ _autowiredPropertyTypes.Add(typeof(ValueAttribute));
+ }
///
/// Determines the candidate constructors to use for the given object.
@@ -296,46 +305,59 @@ namespace Spring.Objects.Factory.Attributes
do
{
- var currElements = new List();
- foreach (
- var property in
- objectType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
+ foreach (var autowiredType in _autowiredPropertyTypes)
{
- var attr = Attribute.GetCustomAttribute(property, _autowiredPropertyType) as AutowiredAttribute;
- if (attr != null && property.DeclaringType == objectType)
- currElements.Add(new AutowiredPropertyElement(property, attr.Required));
- }
- foreach (
- var field in
- objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
- {
- var attr = Attribute.GetCustomAttribute(field, _autowiredPropertyType) as AutowiredAttribute;
- if (attr != null && field.DeclaringType == objectType)
- currElements.Add(new AutowiredFieldElement(field, attr.Required));
- }
- foreach (
- var method in
- objectType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
- {
- var attr = Attribute.GetCustomAttribute(method, _autowiredPropertyType) as AutowiredAttribute;
- if (attr != null && method.DeclaringType == objectType)
+ var currElements = new List();
+ foreach (
+ var property in
+ objectType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public |
+ BindingFlags.Instance))
{
- if (method.IsStatic)
- {
- Logger.Warn(
- m => m("Autowired annotation is not supported on static methods: " + method.Name));
- continue;
- }
- if (method.IsGenericMethod)
- {
- Logger.Warn(
- m => m("Autowired annotation is not supported on generic methods: " + method.Name));
- continue;
- }
- currElements.Add(new AutowiredMethodElement(method, attr.Required));
+ var required = true;
+ var attr = Attribute.GetCustomAttribute(property, autowiredType);
+ if (attr is AutowiredAttribute)
+ required = ((AutowiredAttribute)attr).Required;
+ if (attr != null && property.DeclaringType == objectType)
+ currElements.Add(new AutowiredPropertyElement(property, required));
}
+ foreach (
+ var field in
+ objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
+ {
+ var required = true;
+ var attr = Attribute.GetCustomAttribute(field, autowiredType);
+ if (attr is AutowiredAttribute)
+ required = ((AutowiredAttribute) attr).Required;
+ if (attr != null && field.DeclaringType == objectType)
+ currElements.Add(new AutowiredFieldElement(field, required));
+ }
+ foreach (
+ var method in
+ objectType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
+ {
+ var required = true;
+ var attr = Attribute.GetCustomAttribute(method, autowiredType);
+ if (attr is AutowiredAttribute)
+ required = ((AutowiredAttribute)attr).Required;
+ if (attr != null && method.DeclaringType == objectType)
+ {
+ if (method.IsStatic)
+ {
+ Logger.Warn(
+ m => m("Autowired annotation is not supported on static methods: " + method.Name));
+ continue;
+ }
+ if (method.IsGenericMethod)
+ {
+ Logger.Warn(
+ m => m("Autowired annotation is not supported on generic methods: " + method.Name));
+ continue;
+ }
+ currElements.Add(new AutowiredMethodElement(method, required));
+ }
+ }
+ elements.InsertRange(0, currElements);
}
- elements.InsertRange(0, currElements);
objectType = objectType.BaseType;
} while (objectType != null && objectType != typeof (Object));
diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAnnotationAutowireCandidateResolver.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAnnotationAutowireCandidateResolver.cs
new file mode 100644
index 00000000..e521ac5f
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAnnotationAutowireCandidateResolver.cs
@@ -0,0 +1,295 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Spring.Core;
+using Spring.Core.TypeConversion;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+using Spring.Util;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ ///
+ /// implementation that matches bean definition qualifier
+ /// against on the field or parameter to be autowired.
+ /// Also supports suggested expression values through a attribute.
+ ///
+ public class QualifierAnnotationAutowireCandidateResolver : IAutowireCandidateResolver, IObjectFactoryAware
+ {
+ private IObjectFactory _objectFactory;
+
+ private ISet _qualifierTypes = new HashSet();
+
+ private Type _valueAttributeType = typeof(ValueAttribute);
+
+ public IObjectFactory ObjectFactory
+ {
+ set { _objectFactory = value; }
+ }
+
+ public Type ValueAttributeType
+ {
+ set { _valueAttributeType = value; }
+ }
+
+ ///
+ /// Create a new QualifierAnnotationAutowireCandidateResolver
+ /// for Spring's standard attribute.
+ ///
+ public QualifierAnnotationAutowireCandidateResolver()
+ {
+ _qualifierTypes.Add(typeof(QualifierAttribute));
+ }
+
+ ///
+ /// Create a new QualifierAnnotationAutowireCandidateResolver
+ /// for the given qualifier attribute type.
+ ///
+ /// the qualifier attribute to look for
+ public QualifierAnnotationAutowireCandidateResolver(Type qualifierType)
+ {
+ Trace.Assert(qualifierType != null, "'qualifierType' must not be null");
+ _qualifierTypes.Add(qualifierType);
+ }
+
+ ///
+ /// Create a new QualifierAnnotationAutowireCandidateResolver
+ /// for the given qualifier attribute types.
+ ///
+ /// the qualifier annotations to look for
+ public QualifierAnnotationAutowireCandidateResolver(ISet qualifierTypes) {
+ Trace.Assert(qualifierTypes != null, "'qualifierTypes' must not be null");
+ _qualifierTypes.UnionWith(qualifierTypes);
+ }
+
+ ///
+ /// Register the given type to be used as a qualifier when autowiring.
+ /// This identifies qualifier annotations for direct use (on fields,
+ /// method parameters and constructor parameters) as well as meta
+ /// annotations that in turn identify actual qualifier annotations.
+ /// This implementation only supports annotations as qualifier types.
+ /// The default is Spring's attribute which serves
+ /// as a qualifier for direct use and also as a meta attribute.
+ ///
+ /// the attribute type to register
+ public void AddQualifierType(Type qualifierType) {
+ _qualifierTypes.Add(qualifierType);
+ }
+
+ ///
+ /// Determine whether the provided object definition is an autowire candidate.
+ /// To be considered a candidate the object's autowire-candidate
+ /// attribute must not have been set to 'false'. Also, if an attribute on
+ /// the field or parameter to be autowired is recognized by this bean factory
+ /// as a qualifier , the object must 'match' against the attribute as
+ /// well as any attributes it may contain. The bean definition must contain
+ /// the same qualifier or match by meta attributes. A "value" attribute will
+ /// fallback to match against the bean name or an alias if a qualifier or
+ /// attribute does not match.
+ ///
+ public bool IsAutowireCandidate(ObjectDefinitionHolder odHolder, DependencyDescriptor descriptor)
+ {
+ if (!odHolder.ObjectDefinition.IsAutowireCandidate)
+ {
+ // if explicitly false, do not proceed with qualifier check
+ return false;
+ }
+ if (descriptor == null) {
+ // no qualification necessaryodHolder
+ return true;
+ }
+ bool match = CheckQualifiers(odHolder, descriptor.Attributes);
+ if (match)
+ {
+ MethodParameter methodParam = descriptor.MethodParameter;
+ if (methodParam != null)
+ {
+ var method = methodParam.MethodInfo;
+ if (method == null || method.ReturnType == typeof(void)) {
+ match = CheckQualifiers(odHolder, methodParam.MethodAttributes);
+ }
+ }
+ }
+ return match;
+ }
+
+ ///
+ /// Match the given qualifier annotations against the candidate bean definition.
+ ///
+ protected bool CheckQualifiers(ObjectDefinitionHolder odHolder, Attribute[] annotationsToSearch)
+ {
+ if (annotationsToSearch == null || annotationsToSearch.Length == 0) {
+ return true;
+ }
+ foreach (var attribute in annotationsToSearch)
+ {
+ if (IsQualifier(attribute.GetType()))
+ {
+ if (!CheckQualifier(odHolder, attribute))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Checks whether the given attribute type is a recognized qualifier type.
+ ///
+ protected bool IsQualifier(Type attributeType)
+ {
+ foreach (Type qualifierType in _qualifierTypes)
+ {
+ if (IsSubTypeOf(attributeType, qualifierType))
+ return true;
+ }
+ return false;
+ }
+
+ private bool IsSubTypeOf(Type actual, Type requested)
+ {
+ do
+ {
+ if (actual == requested)
+ return true;
+
+ actual = actual.BaseType;
+ } while (actual != typeof(Object));
+
+ return false;
+ }
+
+ ///
+ /// Match the given qualifier attribute against the candidate bean definition.
+ ///
+ protected bool CheckQualifier(ObjectDefinitionHolder odHolder, Attribute attribute)
+ {
+ Type type = attribute.GetType();
+ RootObjectDefinition od = (RootObjectDefinition) odHolder.ObjectDefinition;
+ AutowireCandidateQualifier qualifier = od.GetQualifier(type.FullName);
+ if (qualifier == null) {
+ qualifier = od.GetQualifier(type.Name);
+ }
+ if (qualifier == null) {
+ Attribute targetAttribute = null;
+ // TODO: Get the resolved factory method
+ //if (od.GetResolvedFactoryMethod() != null) {
+ // targetAttribute = Attribute.GetCustomAttribute(od.GetResolvedFactoryMethod(), type);
+ //}
+ if (targetAttribute == null) {
+ // look for matching attribute on the target class
+ if (_objectFactory != null) {
+ Type objectType = od.ObjectType;
+ if (objectType != null)
+ {
+ targetAttribute = Attribute.GetCustomAttribute(objectType, type);
+ }
+ }
+ if (targetAttribute == null && od.ObjectType != null) {
+ targetAttribute = Attribute.GetCustomAttribute(od.ObjectType, type);
+ }
+ }
+ if (targetAttribute != null && targetAttribute.Equals(attribute)) {
+ return true;
+ }
+ }
+
+ IDictionary attributes = AttributeUtils.GetAttributeProperties(attribute);
+ if (attributes.Count == 0 && qualifier == null) {
+ // if no attributes, the qualifier must be present
+ return false;
+ }
+ foreach(var entry in attributes)
+ {
+ string propertyName = entry.Key;
+ object expectedValue = entry.Value;
+ object actualValue = null;
+ // check qualifier first
+ if (qualifier != null)
+ {
+ actualValue = qualifier.GetAttribute(propertyName);
+ }
+ if (actualValue == null)
+ {
+ // fall back on bean definition attribute
+ actualValue = od.GetAttribute(propertyName);
+ }
+ if (actualValue == null && propertyName.Equals(AutowireCandidateQualifier.VALUE_KEY) &&
+ expectedValue is string && odHolder.MatchesName((string) expectedValue))
+ {
+ // fall back on bean name (or alias) match
+ continue;
+ }
+ if (actualValue == null && qualifier != null)
+ {
+ // fall back on default, but only if the qualifier is present
+ actualValue = AttributeUtils.GetDefaultValue(attribute, propertyName);
+ }
+ if (actualValue != null)
+ {
+ actualValue = TypeConversionUtils.ConvertValueIfNecessary(expectedValue.GetType(), actualValue, null);
+ }
+ if (!expectedValue.Equals(actualValue)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Determine whether the given dependency carries a value attribute.
+ ///
+ public Object GetSuggestedValue(DependencyDescriptor descriptor)
+ {
+ Object value = FindValue(descriptor.Attributes);
+ if (value == null)
+ {
+ MethodParameter methodParam = descriptor.MethodParameter;
+ if (methodParam != null)
+ {
+ value = FindValue(methodParam.MethodAttributes);
+ }
+ }
+ return value;
+ }
+
+ ///
+ /// Determine a suggested value from any of the given candidate annotations.
+ ///
+ protected Object FindValue(Attribute[] annotationsToSearch) {
+ foreach(var attribute in annotationsToSearch) {
+ if (_valueAttributeType == attribute.GetType())
+ {
+ Object value = ((ValueAttribute)attribute).Expression;
+ if (value == null)
+ {
+ throw new InvalidOperationException("Value attribute must have a value attribute");
+ }
+ return value;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAttribute.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAttribute.cs
index bf2e34ba..c6ef6f43 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAttribute.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/QualifierAttribute.cs
@@ -13,20 +13,52 @@ namespace Spring.Objects.Factory.Attributes
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class QualifierAttribute : Attribute
{
- private readonly string _name;
+ private readonly string _value;
///
- /// Instantiate a new qualifier type
+ /// Instantiate a new qualifier with an empty name
///
- /// name to use as qualifier
- public QualifierAttribute(string name)
+ public QualifierAttribute()
{
- _name = name;
+ _value = "";
+ }
+
+ ///
+ /// Instantiate a new qualifier with a givin name
+ ///
+ /// name to use as qualifier
+ public QualifierAttribute(string value)
+ {
+ _value = value;
}
///
/// Gets the name associated with this qualifier
///
- public string Name { get { return _name; } }
+ public string Value { get { return _value; } }
+
+
+ ///
+ /// Checks weather the attribute is the same
+ ///
+ ///
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj == null || GetType() != obj.GetType())
+ {
+ return false;
+ }
+
+ var o1 = obj as QualifierAttribute;
+ if (_value != o1._value) return false;
+
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return _value != null ? _value.GetHashCode() : 0;
+ }
}
}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/ValueAttribute.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/ValueAttribute.cs
new file mode 100644
index 00000000..62155b4c
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/ValueAttribute.cs
@@ -0,0 +1,37 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
+ public class ValueAttribute : Attribute
+ {
+ private string _expression;
+
+ public ValueAttribute(string expression)
+ {
+ _expression = expression;
+ }
+
+ public string Expression { get { return _expression; } }
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/DependencyDescriptor.cs b/src/Spring/Spring.Core/Objects/Factory/Config/DependencyDescriptor.cs
index cecbebe7..f891798a 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/DependencyDescriptor.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/DependencyDescriptor.cs
@@ -168,7 +168,28 @@ namespace Spring.Objects.Factory.Config
get { return methodParameter; }
}
- public string Name
+ ///
+ /// Gets the Attributes assigned to Field, Property or Paramater
+ ///
+ public Attribute[] Attributes
+ {
+ get
+ {
+ if (methodParameter != null)
+ return methodParameter.ParameterAttributes;
+ if (property != null)
+ return Attribute.GetCustomAttributes(property);
+ if (field != null)
+ return Attribute.GetCustomAttributes(field);
+
+ return new Attribute[0];
+ }
+ }
+
+ ///
+ /// Gets the name of the member info
+ ///
+ public string DependencyName
{
get
{
@@ -182,68 +203,5 @@ namespace Spring.Objects.Factory.Config
return "";
}
}
-
- ///
- /// Determine whether the given dependency carries a value annotation.
- ///
- public Object GetSuggestedValue()
- {
- Object value = null;
-
- if (methodParameter != null)
- value = ConvertFieldName(methodParameter.ParameterName());
- if (property != null)
- value = property.Name;
- if (field != null)
- value = ConvertFieldName(field.Name);
-
- return value;
- }
-
- ///
- /// Get the qualifier name if exists
- ///
- public string GetQualifierName()
- {
- string value = null;
-
- if (methodParameter != null)
- value = FindValue(methodParameter.GetParameterAttributes());
- if (property != null)
- value = FindValue(Attribute.GetCustomAttributes(property));
- if (field != null)
- value = FindValue(Attribute.GetCustomAttributes(field));
-
- return value;
- }
-
- /**
- * Determine a suggested value from any of the given candidate annotations.
- */
-
- private string FindValue(Attribute[] attributesToSearch)
- {
- foreach (Attribute attribute in attributesToSearch)
- {
- if (attribute is QualifierAttribute)
- {
- var qualifierAttribute = attribute as QualifierAttribute;
- return qualifierAttribute.Name;
- }
- }
- return null;
- }
-
- private string ConvertFieldName(string fieldName)
- {
- if (string.IsNullOrEmpty(fieldName))
- return string.Empty;
-
- char[] letters = fieldName.TrimStart('_').ToCharArray();
- letters[0] = char.ToUpper(letters[0]);
-
- return new string(letters);
- }
-
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableObjectFactory.cs
index 52678387..e81168a5 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableObjectFactory.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableObjectFactory.cs
@@ -22,6 +22,7 @@
using System;
using System.ComponentModel;
+using Spring.Util;
#endregion
@@ -163,5 +164,17 @@ namespace Spring.Objects.Factory.Config
///
void RegisterCustomConverter(Type requiredType, TypeConverter converter);
+ ///
+ /// Add a String resolver for embedded values such as annotation attributes.
+ ///
+ /// the String resolver to apply to embedded values
+ void AddEmbeddedValueResolver(IStringValueResolver valueResolver);
+
+ ///
+ /// Resolve the given embedded value, e.g. an annotation attribute.
+ ///
+ /// the value to resolve
+ /// the resolved value (may be the original value as-is)
+ string ResolveEmbeddedValue(string value);
}
}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/IObjectDefinition.cs b/src/Spring/Spring.Core/Objects/Factory/Config/IObjectDefinition.cs
index 81f19b3d..fbc180ca 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/IObjectDefinition.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/IObjectDefinition.cs
@@ -226,5 +226,12 @@ namespace Spring.Objects.Factory.Config
/// true if this instance is autowire candidate; otherwise, false .
///
bool IsAutowireCandidate { get; }
+
+ ///
+ /// Return whether this bean is a primary autowire candidate.
+ /// If this value is true for exactly one bean among multiple
+ /// matching candidates, it will serve as a tie-breaker.
+ ///
+ bool IsPrimary { get; }
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/ObjectDefinitionHolder.cs b/src/Spring/Spring.Core/Objects/Factory/Config/ObjectDefinitionHolder.cs
index 4fa884b9..ff010302 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/ObjectDefinitionHolder.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/ObjectDefinitionHolder.cs
@@ -132,6 +132,17 @@ namespace Spring.Objects.Factory.Config
get { return aliases; }
}
+ ///
+ /// Checks wether a givin candidate name has a defined object or alias
+ ///
+ /// name to check if exists
+ ///
+ public bool MatchesName(string candidateName)
+ {
+ return (!string.IsNullOrEmpty(candidateName) &&
+ (candidateName.Equals(ObjectName) || Aliases.Contains(candidateName)));
+ }
+
#endregion
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs b/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs
index 017d5f40..a0c862cd 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs
@@ -28,6 +28,7 @@ using System.Globalization;
using Common.Logging;
using Spring.Collections;
+using Spring.Util;
#endregion
@@ -247,13 +248,10 @@ namespace Spring.Objects.Factory.Config
definition.ResourceDescription, name, ex.Message);
}
}
+
+ factory.AddEmbeddedValueResolver(resolveAdapter);
}
-
-
-
-
-
///
/// Parse values recursively to be able to resolve cross-references between
/// placeholder values.
@@ -401,7 +399,7 @@ namespace Spring.Objects.Factory.Config
#region Helper class
- private class PlaceholderResolveHandlerAdapter
+ private class PlaceholderResolveHandlerAdapter : IStringValueResolver
{
private readonly PropertyPlaceholderConfigurer ppc;
private readonly NameValueCollection props;
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs
index e12ba0ae..598a6dd8 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs
@@ -22,13 +22,15 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Globalization;
+using System.Linq;
using System.Reflection;
using System.Text;
-
using Spring.Core.TypeResolution;
using Spring.Objects.Factory.Config;
using Spring.Util;
+using Spring.Collections.Generic;
#endregion
@@ -44,7 +46,7 @@ namespace Spring.Objects.Factory.Support
/// Juergen Hoeller
/// Rick Evans (.NET)
[Serializable]
- public abstract class AbstractObjectDefinition : IConfigurableObjectDefinition
+ public abstract class AbstractObjectDefinition : ObjectMetadataAttributeAccessor, IConfigurableObjectDefinition
{
private static readonly string SCOPE_SINGLETON = "singleton";
private static readonly string SCOPE_PROTOTYPE = "prototype";
@@ -135,6 +137,8 @@ namespace Spring.Objects.Factory.Support
InitMethodName = other.InitMethodName;
DestroyMethodName = other.DestroyMethodName;
IsAutowireCandidate = other.IsAutowireCandidate;
+ IsPrimary = other.IsPrimary;
+ CopyQualifiersFrom(aod);
DependsOn = new List(other.DependsOn);
FactoryMethodName = other.FactoryMethodName;
FactoryObjectName = other.FactoryObjectName;
@@ -541,6 +545,67 @@ namespace Spring.Objects.Factory.Support
set { autowireCandidate = value;}
}
+
+ ///
+ /// Set whether this bean is a primary autowire candidate.
+ /// If this value is true for exactly one bean among multiple
+ /// matching candidates, it will serve as a tie-breaker.
+ ///
+ public bool IsPrimary
+ {
+ get { return primary; }
+ set { primary = value; }
+ }
+
+ ///
+ /// Register a qualifier to be used for autowire candidate resolution,
+ /// keyed by the qualifier's type name.
+ ///
+ ///
+ public void AddQualifier(AutowireCandidateQualifier qualifier)
+ {
+ qualifiers.Add(qualifier.TypeName, qualifier);
+ }
+
+ ///
+ /// Return whether this bean has the specified qualifier.
+ ///
+ public bool HasQualifier(string typeName)
+ {
+ return qualifiers.ContainsKey(typeName);
+ }
+
+ ///
+ /// Return the qualifier mapped to the provided type name.
+ ///
+ public AutowireCandidateQualifier GetQualifier(string typeName)
+ {
+ return qualifiers.ContainsKey(typeName) ? qualifiers[typeName] : null;
+ }
+
+ ///
+ /// Return all registered qualifiers.
+ ///
+ /// the Set of objects.
+ public Set GetQualifiers()
+ {
+ return new OrderedSet(qualifiers.Values);
+ }
+
+ ///
+ /// Copy the qualifiers from the supplied AbstractBeanDefinition to this bean definition.
+ ///
+ /// the AbstractBeanDefinition to copy from
+ public void CopyQualifiersFrom(AbstractObjectDefinition source)
+ {
+ Trace.Assert(source != null, "Source must not be null");
+ foreach (var qualifier in source.qualifiers)
+ {
+ if (!qualifiers.Contains(qualifier))
+ qualifiers.Add(qualifier);
+ }
+ }
+
///
/// The name of the initializer method.
///
@@ -748,6 +813,7 @@ namespace Spring.Objects.Factory.Support
}
AutowireMode = other.AutowireMode;
ResourceDescription = other.ResourceDescription;
+ IsPrimary = other.IsPrimary;
AbstractObjectDefinition aod = other as AbstractObjectDefinition;
if (aod != null)
@@ -759,6 +825,7 @@ namespace Spring.Objects.Factory.Support
MethodOverrides.AddAll(aod.MethodOverrides);
DependencyCheck = aod.DependencyCheck;
+ CopyQualifiersFrom(aod);
}
}
@@ -779,6 +846,7 @@ namespace Spring.Objects.Factory.Support
buffer.Append("; Singleton = ").Append(IsSingleton);
buffer.Append("; LazyInit = ").Append(IsLazyInit);
buffer.Append("; Autowire = ").Append(AutowireMode);
+ buffer.Append("; Primary = ").Append(IsPrimary);
buffer.Append("; DependencyCheck = ").Append(DependencyCheck);
buffer.Append("; InitMethodName = ").Append(InitMethodName);
buffer.Append("; DestroyMethodName = ").Append(DestroyMethodName);
@@ -811,6 +879,12 @@ namespace Spring.Objects.Factory.Support
private DependencyCheckingMode dependencyCheck = DependencyCheckingMode.None;
private IList dependsOn;
private bool autowireCandidate = true;
+
+ private bool primary;
+
+ private readonly IDictionary qualifiers =
+ new Dictionary();
+
private string initMethodName = null;
private string destroyMethodName = null;
private string factoryMethodName = null;
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs
index 446336bd..72c66b3d 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs
@@ -1603,6 +1603,11 @@ namespace Spring.Objects.Factory.Support
///
private ISet objectPostProcessors = new SortedSet(new ObjectOrderComparator());
+ ///
+ /// String Resolver applied to Autowired value injections
+ ///
+ private ISet embeddedValueResolvers = new SortedSet();
+
///
/// Indicates whether any IInstantiationAwareBeanPostProcessors have been registered
///
@@ -2385,6 +2390,30 @@ namespace Spring.Objects.Factory.Support
return this.singletonsInCreation.Contains(name);
}
+ ///
+ /// Add a String resolver for embedded values such as annotation attributes.
+ ///
+ /// the String resolver to apply to embedded values
+ public void AddEmbeddedValueResolver(IStringValueResolver valueResolver)
+ {
+ embeddedValueResolvers.Add(valueResolver);
+ }
+
+ ///
+ /// Resolve the given embedded value, e.g. an annotation attribute.
+ ///
+ /// the value to resolve
+ /// the resolved value (may be the original value as-is)
+ public string ResolveEmbeddedValue(string value)
+ {
+ string result = value;
+ foreach(IStringValueResolver resolver in embeddedValueResolvers)
+ {
+ result = resolver.ParseAndResolveVariables(result);
+ }
+ return result;
+ }
+
///
/// Add a new
/// that will get applied to objects created by this factory.
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AutowireCandidateQualifier.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AutowireCandidateQualifier.cs
new file mode 100644
index 00000000..790c9151
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/AutowireCandidateQualifier.cs
@@ -0,0 +1,102 @@
+#region License
+
+/*
+/// Copyright 2002-2010 the original author or authors.
+ *
+/// Licensed under the Apache License, Version 2.0 (the "License");
+/// you may not use this file except in compliance with the License.
+/// You may obtain a copy of the License at
+ *
+/// http://www.apache.org/licenses/LICENSE-2.0
+ *
+/// Unless required by applicable law or agreed to in writing, software
+/// distributed under the License is distributed on an "AS IS" BASIS,
+/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+/// See the License for the specific language governing permissions and
+/// limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+
+namespace Spring.Objects.Factory.Support
+{
+ ///
+ /// Qualifier for resolving autowire candidates. A bean definition that
+ /// includes one or more such qualifiers enables fine-grained matching
+ /// against annotations on a field or parameter to be autowired.
+ ///
+ public class AutowireCandidateQualifier : ObjectMetadataAttributeAccessor
+ {
+ public static string VALUE_KEY = "Value";
+
+ private readonly string _typeName;
+
+
+ ///
+ /// Construct a qualifier to match against an annotation of the
+ /// given type.
+ ///
+ /// type the annotation type
+ public AutowireCandidateQualifier(Type type) : this(type.Name)
+ {
+ }
+
+ ///
+ /// Construct a qualifier to match against an annotation of the
+ /// given type name.
+ /// The type name may match the fully-qualified class name of
+ /// the annotation or the short class name (without the package).
+ ///
+ /// the name of the annotation type
+ public AutowireCandidateQualifier(string typeName)
+ {
+ Trace.Assert(typeName != null, "Type name must not be null");
+ _typeName = typeName;
+ }
+
+ ///
+ /// Construct a qualifier to match against an annotation of the
+ /// given type whose value attribute also matches
+ /// the specified value.
+ ///
+ /// the annotation type
+ /// the annotation value to match
+ public AutowireCandidateQualifier(Type type, object value) : this(type.Name, value)
+ {
+ }
+
+ ///
+ /// Construct a qualifier to match against an annotation of the
+ /// given type name whose value attribute also matches
+ /// the specified value.
+ /// The type name may match the fully-qualified class name of
+ /// the annotation or the short class name (without the package).
+ ///
+ /// the name of the annotation type
+ /// the annotation value to match
+ public AutowireCandidateQualifier(string typeName, object value)
+ {
+ Trace.Assert(typeName != null, "Type name must not be null");
+ _typeName = typeName;
+ SetAttribute(VALUE_KEY, value);
+ }
+
+
+ ///
+ /// Retrieve the type name. This value will be the same as the
+ /// type name provided to the constructor or the fully-qualified
+ /// class name if a Class instance was provided to the constructor.
+ ///
+ public String TypeName
+ {
+ get { return _typeName; }
+ }
+
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AutowireUtils.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AutowireUtils.cs
index b68e6747..70d6734e 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/AutowireUtils.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/AutowireUtils.cs
@@ -27,6 +27,7 @@ using System.Reflection;
using Spring.Collections;
using Spring.Core;
+using Spring.Objects.Factory.Attributes;
using Spring.Objects.Factory.Config;
using Spring.Util;
@@ -348,7 +349,7 @@ namespace Spring.Objects.Factory.Support
/// A SimpleAutowireCandidateResolver
public static IAutowireCandidateResolver CreateAutowireCandidateResolver()
{
- return new SimpleAutowireCandidateResolver();
+ return new QualifierAnnotationAutowireCandidateResolver();
}
///
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs
index f9b33de6..bad5a33d 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs
@@ -25,6 +25,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
+using System.Linq;
using Common.Logging;
@@ -32,6 +33,8 @@ using Spring.Core;
using Spring.Core.TypeConversion;
using Spring.Objects.Factory.Config;
using Spring.Util;
+using Spring.Expressions;
+using Spring.Context.Support;
#endregion
@@ -324,7 +327,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 Dictionary();
#endregion
@@ -523,7 +526,7 @@ namespace Spring.Objects.Factory.Support
{
AssertUtils.IsTrue((autowiredValue is IObjectFactory) || dependencyType.IsInstanceOfType(autowiredValue),
"Value [" + autowiredValue + "] does not implement specified type [" + dependencyType.Name + "]");
- if (!resolvableDependencies.Contains(dependencyType))
+ if (!resolvableDependencies.ContainsKey(dependencyType))
{
this.resolvableDependencies.Add(dependencyType, autowiredValue);
}
@@ -1111,22 +1114,20 @@ namespace Spring.Objects.Factory.Support
public override object ResolveDependency(DependencyDescriptor descriptor, string objectName,
IList autowiredObjectNames)
{
- string qualifierName = descriptor.GetQualifierName();
- if (!string.IsNullOrEmpty(qualifierName))
- {
- if (ContainsObject(qualifierName))
- {
- autowiredObjectNames.Add(qualifierName);
- return GetObject(qualifierName);
- }
- else
- {
- if (descriptor.Required)
- throw new NoSuchObjectDefinitionException(qualifierName, "no object found with this name");
- return null;
- }
- }
Type type = descriptor.DependencyType;
+ Object value = AutowireCandidateResolver.GetSuggestedValue(descriptor);
+ if (value != null)
+ {
+ if (value is string)
+ {
+ object valueBefore = value;
+ value = ResolveEmbeddedValue((string) value);
+ if (valueBefore.Equals(value))
+ value = ExpressionEvaluator.GetValue(null, (string) value);
+ }
+ return TypeConversionUtils.ConvertValueIfNecessary(type, value, null);
+ }
+
if (type.IsArray)
{
Type elementType = type.GetElementType();
@@ -1189,20 +1190,6 @@ namespace Spring.Objects.Factory.Support
else
{
IDictionary matchingObjects = FindAutowireCandidates(objectName, type, descriptor);
- if (matchingObjects.Count == 0 || matchingObjects.Count > 1)
- {
- Object value = descriptor.GetSuggestedValue();
- if (value is string)
- {
- string matchingObject = value as string;
- if (ContainsObject(matchingObject))
- {
- matchingObjects.Clear();
- matchingObjects.Add(matchingObject, GetObject(matchingObject));
- }
- }
- }
-
if (matchingObjects.Count == 0)
{
if (descriptor.Required)
@@ -1216,8 +1203,17 @@ namespace Spring.Objects.Factory.Support
}
if (matchingObjects.Count > 1)
{
- throw new NoSuchObjectDefinitionException(type,
- "expected single matching object but found " + matchingObjects.Count + ": " + matchingObjects);
+ string primaryObjecName = DeterminePrimaryCandidate(matchingObjects, descriptor);
+ if (primaryObjecName == null)
+ {
+ throw new NoSuchObjectDefinitionException(type,
+ "expected single matching object but found " + matchingObjects.Count + ": " + matchingObjects);
+ }
+ if (autowiredObjectNames != null)
+ {
+ autowiredObjectNames.Add(primaryObjecName);
+ }
+ return matchingObjects[primaryObjecName];
}
DictionaryEntry entry = (DictionaryEntry)ObjectUtils.EnumerateFirstElement(matchingObjects);
if (autowiredObjectNames != null)
@@ -1228,7 +1224,75 @@ namespace Spring.Objects.Factory.Support
}
}
+ ///
+ /// Determine the primary autowire candidate in the given set of beans.
+ ///
+ /// a Map of candidate names and candidate instances
+ /// that match the required type
+ /// the target dependency to match against
+ /// the name of the primary candidate, or null if none found
+ private string DeterminePrimaryCandidate(IDictionary candidateObjects, DependencyDescriptor descriptor) {
+ string primaryObjectName = null;
+ string fallbackObjectName = null;
+ foreach(DictionaryEntry entry in candidateObjects)
+ {
+ string candidateBeanName = entry.Key as string;
+ object objectInstance = entry.Value;
+ if (IsPrimary(candidateBeanName, objectInstance))
+ {
+ if (primaryObjectName != null)
+ {
+ bool candidateLocal = ContainsObjectDefinition(candidateBeanName);
+ bool primaryLocal = ContainsObjectDefinition(primaryObjectName);
+ if (candidateLocal == primaryLocal)
+ {
+ throw new NoSuchObjectDefinitionException(descriptor.DependencyType,
+ "more than one 'primary' bean found among candidates: " + candidateObjects);
+ }
+ if (candidateLocal && !primaryLocal)
+ {
+ primaryObjectName = candidateBeanName;
+ }
+ }
+ else
+ {
+ primaryObjectName = candidateBeanName;
+ }
+ }
+ if (primaryObjectName == null &&
+ (resolvableDependencies.Values.Contains(objectInstance) ||
+ MatchesObjectName(candidateBeanName, descriptor.DependencyName)))
+ {
+ fallbackObjectName = candidateBeanName;
+ }
+ }
+ return (primaryObjectName != null ? primaryObjectName : fallbackObjectName);
+ }
+ ///
+ /// Return whether the object definition for the given object name has been
+ /// marked as a primary object.
+ ///
+ /// the name of the bean
+ /// the corresponding bean instance
+ /// whether the given bean qualifies as primary
+ private bool IsPrimary(string objectName, object objectInstance) {
+ if (ContainsObjectDefinition(objectName)) {
+ return GetMergedObjectDefinition(objectName, true).IsPrimary;
+ }
+ return (ParentObjectFactory is DefaultListableObjectFactory &&
+ ((DefaultListableObjectFactory)ParentObjectFactory).IsPrimary(objectName, objectInstance));
+ }
+
+ ///
+ /// Determine whether the given candidate name matches the bean name or the aliases
+ ///stored in this bean definition.
+ ///
+ protected bool MatchesObjectName(string objectName, string candidateName)
+ {
+ return (candidateName != null &&
+ (candidateName.Equals(objectName) || GetAliases(objectName).Contains(candidateName)));
+ }
///
/// Raises the no such object definition exception for an unresolvable dependency
@@ -1248,9 +1312,9 @@ namespace Spring.Objects.Factory.Support
ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.Eager);
IDictionary result = new OrderedDictionary(candidateNames.Count);
- foreach (DictionaryEntry entry in resolvableDependencies)
+ foreach (var entry in resolvableDependencies)
{
- Type autoWiringType = (Type)entry.Key;
+ Type autoWiringType = entry.Key;
if (autoWiringType.IsAssignableFrom(requiredType))
{
object autowiringValue = this.resolvableDependencies[autoWiringType];
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/IAutowireCandidateResolver.cs b/src/Spring/Spring.Core/Objects/Factory/Support/IAutowireCandidateResolver.cs
index 199a4a08..4dfeff37 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/IAutowireCandidateResolver.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/IAutowireCandidateResolver.cs
@@ -18,6 +18,7 @@
#endregion
+using System;
using Spring.Objects.Factory.Config;
namespace Spring.Objects.Factory.Support
@@ -41,5 +42,16 @@ namespace Spring.Objects.Factory.Support
/// true if the object definition qualifies as autowire candidate; otherwise, false .
///
bool IsAutowireCandidate(ObjectDefinitionHolder odHolder, DependencyDescriptor descriptor);
+
+
+ ///
+ /// Determine whether a default value is suggested for the given dependency.
+ ///
+ /// The descriptor for the target method parameter or field
+ /// The value suggested (typically an expression String),
+ /// or null if none found
+ ///
+ Object GetSuggestedValue(DependencyDescriptor descriptor);
+
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/SimpleAutowireCandidateResolver.cs b/src/Spring/Spring.Core/Objects/Factory/Support/SimpleAutowireCandidateResolver.cs
index 52551da3..9df13e0f 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/SimpleAutowireCandidateResolver.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/SimpleAutowireCandidateResolver.cs
@@ -45,5 +45,18 @@ namespace Spring.Objects.Factory.Support
{
return odHolder.ObjectDefinition.IsAutowireCandidate;
}
+
+
+ ///
+ /// Determine whether a default value is suggested for the given dependency.
+ ///
+ /// The descriptor for the target method parameter or field
+ /// The value suggested (typically an expression String),
+ /// or null if none found
+ ///
+ public object GetSuggestedValue(DependencyDescriptor descriptor)
+ {
+ return null;
+ }
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionConstants.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionConstants.cs
index 064e02e9..51c9835e 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionConstants.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionConstants.cs
@@ -298,6 +298,11 @@ namespace Spring.Objects.Factory.Xml
///
///
public const string PropertyElement = "property";
+
+ ///
+ /// A qualifier definition used for fine grained autowiring
+ ///
+ public const string QualifierElement = "qualifier";
///
/// A reference to another managed object or static
@@ -581,6 +586,16 @@ namespace Spring.Objects.Factory.Xml
///
public const string AutowireAttribute = "autowire";
+ ///
+ /// Attribute element to farther deifne the qualifier of an object
+ ///
+ public const string AttributeElement = "attribute";
+
+ ///
+ /// The primary object for autwired injection
+ ///
+ public const string PrimaryAttribute = "primary";
+
///
/// Shortcut alternative to specifying a key element in a
/// dictionary entry element with <ref object="..."/> .
@@ -598,6 +613,11 @@ namespace Spring.Objects.Factory.Xml
///
public const string MergeAttribute = "merge";
+ ///
+ /// Defined meta attributes to be used for Autowire objects
+ ///
+ public const string MetaElement = "meta";
+
///
/// The string of characters that delimit object names.
///
diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs
index 4f2a34a8..2188fdf1 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs
@@ -61,7 +61,7 @@ namespace Spring.Objects.Factory.Xml
NamespaceParser(
Namespace = "http://www.springframework.net",
SchemaLocationAssemblyHint = typeof(ObjectsNamespaceParser),
- SchemaLocation = "/Spring.Objects.Factory.Xml/spring-objects-1.3.xsd"
+ SchemaLocation = "/Spring.Objects.Factory.Xml/spring-objects-2.0.xsd"
)
]
// [Obsolete("ObjectsNamespaceParser will be dropped with 2.x, use ObjectDefinitionParserHelper instead", false)]
@@ -446,6 +446,8 @@ namespace Spring.Objects.Factory.Xml
ParserContext childParserContext = new ParserContext(parserContext.ParserHelper, od);
+ ParseMetaElements(element, od);
+ ParseQualifierElements(id, element, parserContext, od);
MutablePropertyValues pvs = ParsePropertyElements(id, element, childParserContext);
ConstructorArgumentValues arguments = ParseConstructorArgSubElements(id, element, childParserContext);
EventValues events = ParseEventHandlerSubElements(id, element, childParserContext);
@@ -479,6 +481,12 @@ namespace Spring.Objects.Factory.Xml
autowire = childParserContext.ParserHelper.Defaults.Autowire;
}
od.AutowireMode = GetAutowireMode(autowire);
+ string primary = GetAttributeValue(element, ObjectDefinitionConstants.PrimaryAttribute);
+ if (primary == null)
+ {
+ primary = "false";
+ }
+ od.IsPrimary = IsTrueStringValue(primary);
string initMethodName = GetAttributeValue(element, ObjectDefinitionConstants.InitMethodAttribute);
if (StringUtils.HasText(initMethodName))
{
@@ -647,6 +655,76 @@ namespace Spring.Objects.Factory.Xml
return events;
}
+ ///
+ /// Parse the meta upplied meta attributes if the given object element
+ ///
+ protected void ParseMetaElements(XmlElement element, ObjectMetadataAttributeAccessor attributeAccessor)
+ {
+ foreach (XmlNode node in this.SelectNodes(element, ObjectDefinitionConstants.MetaElement))
+ {
+ string key = GetAttributeValue((XmlElement)node, ObjectDefinitionConstants.KeyAttribute);
+ string value = GetAttributeValue((XmlElement)node, ObjectDefinitionConstants.ValueAttribute);
+
+ ObjectMetadataAttribute attribute = new ObjectMetadataAttribute(key, value);
+ attribute.Source = (XmlElement)node;
+ attributeAccessor.AddMetadataAttribute(attribute);
+ }
+ }
+
+ ///
+ /// Parse qualifier sub-elements of the given bean element.
+ ///
+ public void ParseQualifierElements(string name, XmlElement element, ParserContext parserContext, AbstractObjectDefinition od)
+ {
+ foreach (XmlNode node in this.SelectNodes(element, ObjectDefinitionConstants.QualifierElement))
+ {
+ ParseQualifierElement(name, (XmlElement) node, parserContext, od);
+ }
+ }
+
+ ///
+ /// Parse a qualifier element.
+ ///
+ public void ParseQualifierElement(string name, XmlElement element, ParserContext parserContext, AbstractObjectDefinition od)
+ {
+ string typeName = GetAttributeValue(element, ObjectDefinitionConstants.TypeAttribute);
+ string value = GetAttributeValue(element, ObjectDefinitionConstants.ValueAttribute);
+
+ if (string.IsNullOrEmpty(typeName))
+ {
+ throw new ObjectDefinitionStoreException(
+ parserContext.ReaderContext.Resource, name,
+ "Tag 'qualifier' must have a 'type' attribute");
+ }
+
+ var qualifier = new AutowireCandidateQualifier(typeName);
+ qualifier.Source = element;
+
+ if (!string.IsNullOrEmpty(value))
+ qualifier.SetAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
+
+ foreach (XmlNode node in this.SelectNodes(element, ObjectDefinitionConstants.AttributeElement))
+ {
+ var attributeEle = node as XmlElement;
+ string attributeKey = GetAttributeValue(attributeEle, ObjectDefinitionConstants.KeyAttribute);
+ string attributeValue = GetAttributeValue(attributeEle, ObjectDefinitionConstants.ValueAttribute);
+
+ if (!string.IsNullOrEmpty(attributeKey) && !string.IsNullOrEmpty(attributeValue))
+ {
+ var attribute = new ObjectMetadataAttribute(attributeKey, attributeValue);
+ attribute.Source = attributeEle;
+ qualifier.AddMetadataAttribute(attribute);
+ }
+ else
+ {
+ throw new ObjectDefinitionStoreException(
+ parserContext.ReaderContext.Resource, name,
+ "Qualifier 'attribute' tag must have a 'key' and 'value'");
+ }
+ }
+ od.AddQualifier(qualifier);
+ }
+
///
/// Parse property value subelements of the given object element.
///
diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-2.0.xsd b/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-2.0.xsd
new file mode 100644
index 00000000..c5febc79
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-2.0.xsd
@@ -0,0 +1,595 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines a base type for any required string. Defines a string with a minimum length of 0
+
+
+
+
+
+
+
+
+ Element containing informative text describing the purpose of the enclosing
+ element. Always optional.
+ Used primarily for user documentation of XML object definition documents.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Import an external file containing object definitions into this file.
+
+
+
+
+
+ Defines an additional alias name for an object definition.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines constructor argument.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines property.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines a single named object.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The document root. At least one object definition is required.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-2.0.xsx b/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-2.0.xsx
new file mode 100644
index 00000000..d23d8609
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-2.0.xsx
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_x0028_group1_x0029__XmlChoice left="7243" top="43376" width="5292" height="3757" selected="0" zOrder="15" index="1" expanded="1">
+
+
+
+
+ <_x0028_group1_x0029__XmlChoice left="19095" top="39111" width="5292" height="3757" selected="0" zOrder="25" index="1" expanded="0" />
+
+
+ <_x0028_group1_x0029__XmlChoice left="19095" top="43376" width="5292" height="3757" selected="0" zOrder="29" index="1" expanded="0" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_x0028_group1_x0029__XmlChoice left="7243" top="90291" width="5292" height="3757" selected="0" zOrder="53" index="1" expanded="0" />
+
+
+
+ <_x0028_group1_x0029__XmlChoice left="7243" top="98821" width="5292" height="3757" selected="0" zOrder="57" index="1" expanded="0" />
+
+
+ <_x0028_group1_x0029__XmlChoice left="7243" top="103086" width="5292" height="3757" selected="0" zOrder="60" index="1" expanded="0" />
+
+
+
+
+
+
+
+
+
+
+
+
+ <_x0028_scope_x0029__XmlSimpleType left="13169" top="128676" width="5292" height="3757" selected="0" zOrder="79" index="0" expanded="1" />
+
+
+ <_x0028_lazy-init_x0029__XmlSimpleType left="13169" top="132941" width="5292" height="3757" selected="0" zOrder="83" index="0" expanded="1" />
+
+
+ <_x0028_autowire_x0029__XmlSimpleType left="13169" top="137206" width="5292" height="3757" selected="0" zOrder="87" index="0" expanded="1" />
+
+
+ <_x0028_dependency-check_x0029__XmlSimpleType left="13169" top="141471" width="5292" height="3757" selected="0" zOrder="91" index="0" expanded="1" />
+
+
+
+ <_x0028_group1_x0029__XmlChoice left="7243" top="150001" width="5292" height="3757" selected="0" zOrder="94" index="1" expanded="1">
+
+
+
+
+
+ <_x0028_default-dependency-check_x0029__XmlSimpleType left="13169" top="158531" width="5292" height="3757" selected="0" zOrder="104" index="0" expanded="1" />
+
+
+ <_x0028_default-autowire_x0029__XmlSimpleType left="13169" top="162796" width="5292" height="3757" selected="0" zOrder="108" index="0" expanded="1" />
+
+
+
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Objects/IObjectMetadataElement.cs b/src/Spring/Spring.Core/Objects/IObjectMetadataElement.cs
new file mode 100644
index 00000000..d14d848a
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/IObjectMetadataElement.cs
@@ -0,0 +1,37 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+
+namespace Spring.Objects
+{
+ ///
+ /// Interface to be implemented by bean metadata elements
+ /// that carry a configuration source object.
+ ///
+ public interface IObjectMetadataElement
+ {
+ ///
+ /// Return the configuration source Object for this metadata element
+ /// (may be null).
+ ///
+ Object Source { get; }
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/ObjectMetadataAttribute.cs b/src/Spring/Spring.Core/Objects/ObjectMetadataAttribute.cs
new file mode 100644
index 00000000..b0dcfca0
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/ObjectMetadataAttribute.cs
@@ -0,0 +1,95 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using System.Diagnostics;
+using Spring.Util;
+
+namespace Spring.Objects
+{
+ ///
+ /// Holder for a key-value style attribute that is part of a bean definition.
+ /// Keeps track of the definition source in addition to the key-value pair.
+ ///
+ public class ObjectMetadataAttribute : IObjectMetadataElement
+ {
+ private readonly string _name;
+
+ private readonly object _value;
+
+ private object _source;
+
+
+ ///
+ /// Create a new AttributeValue instance.
+ ///
+ /// the name of the attribute (never null)
+ /// the value of the attribute (possibly before type conversion)
+ public ObjectMetadataAttribute(string name, object value)
+ {
+ Trace.Assert(name != null, "Name must not be null");
+ _name = name;
+ _value = value;
+ }
+
+
+ ///
+ /// Return the name of the attribute.
+ ///
+ public string Name { get { return _name; } }
+
+ ///
+ /// Return the value of the attribute.
+ ///
+ public object Value { get { return _value; } }
+
+ ///
+ /// Set the configuration source Object for this metadata element.
+ /// The exact type of the object will depend on the configuration mechanism used.
+ ///
+ public object Source { get { return _source; } set { _source = value; } }
+
+
+ public override bool Equals(Object other)
+ {
+ if (this == other) {
+ return true;
+ }
+ if (!(other is ObjectMetadataAttribute)) {
+ return false;
+ }
+ var otherMa = (ObjectMetadataAttribute) other;
+ return (_name.Equals(otherMa._name) &&
+ ObjectUtils.NullSafeEquals(_value, otherMa._value) &&
+ ObjectUtils.NullSafeEquals(_source, otherMa._source));
+ }
+
+
+ public override int GetHashCode()
+ {
+ return _name.GetHashCode() * 29 + ObjectUtils.NullSafeHashCode(_value);
+ }
+
+ public override string ToString()
+ {
+ return "metadata attribute '" + _name + "'";
+ }
+ }
+}
diff --git a/src/Spring/Spring.Core/Objects/ObjectMetadataAttributeAccessor.cs b/src/Spring/Spring.Core/Objects/ObjectMetadataAttributeAccessor.cs
new file mode 100644
index 00000000..804ad4e0
--- /dev/null
+++ b/src/Spring/Spring.Core/Objects/ObjectMetadataAttributeAccessor.cs
@@ -0,0 +1,83 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using Spring.Core;
+
+namespace Spring.Objects
+{
+ ///
+ /// Extension of ,
+ /// holding attributes as objects in order
+ /// to keep track of the definition source.
+ ///
+ public class ObjectMetadataAttributeAccessor : AttributeAccessorSupport, IObjectMetadataElement
+ {
+ private object _source;
+
+ ///
+ /// Set the configuration source object for this metadata element.
+ /// The exact type of the object will depend on the configuration mechanism used.
+ ///
+ public object Source
+ {
+ get { return _source; }
+ set { _source = value; }
+ }
+
+ ///
+ /// Add the given BeanMetadataAttribute to this accessor's set of attributes.
+ ///
+ /// The BeanMetadataAttribute object to register
+ public void AddMetadataAttribute(ObjectMetadataAttribute attribute)
+ {
+ base.SetAttribute(attribute.Name, attribute);
+ }
+
+ ///
+ /// Look up the given BeanMetadataAttribute in this accessor's set of attributes.
+ ///
+ /// the name of the attribute
+ /// the corresponding BeanMetadataAttribute object,
+ /// or null if no such attribute defined
+ ///
+ public ObjectMetadataAttribute GetMetadataAttribute(string name)
+ {
+ return (ObjectMetadataAttribute) base.GetAttribute(name);
+ }
+
+ public override void SetAttribute(string name, object value)
+ {
+ base.SetAttribute(name, new ObjectMetadataAttribute(name, value));
+ }
+
+ public override object GetAttribute(string name)
+ {
+ var attribute = (ObjectMetadataAttribute) base.GetAttribute(name);
+ return (attribute != null ? attribute.Value : null);
+ }
+
+ public override object RemoveAttribute(string name)
+ {
+ var attribute = (ObjectMetadataAttribute) base.RemoveAttribute(name);
+ return (attribute != null ? attribute.Value : null);
+ }
+
+ }
+}
diff --git a/src/Spring/Spring.Core/Spring.Core.2008.csproj b/src/Spring/Spring.Core/Spring.Core.2008.csproj
index 3ea6eac4..b376d114 100644
--- a/src/Spring/Spring.Core/Spring.Core.2008.csproj
+++ b/src/Spring/Spring.Core/Spring.Core.2008.csproj
@@ -278,12 +278,14 @@
Code
+
Code
+
@@ -673,8 +675,14 @@
Code
+
+
+
+
+
+
@@ -708,9 +716,13 @@
+
+
+
+
@@ -1141,6 +1153,7 @@
+
@@ -1229,6 +1242,7 @@
+
diff --git a/src/Spring/Spring.Core/Spring.Core.2010.csproj b/src/Spring/Spring.Core/Spring.Core.2010.csproj
index ced462ac..13c850fd 100644
--- a/src/Spring/Spring.Core/Spring.Core.2010.csproj
+++ b/src/Spring/Spring.Core/Spring.Core.2010.csproj
@@ -280,12 +280,14 @@
Code
+
Code
+
@@ -678,9 +680,11 @@
+
+
@@ -714,9 +718,13 @@
+
+
+
+
@@ -1147,6 +1155,7 @@
+
@@ -1236,6 +1245,9 @@
+
+ Designer
+
diff --git a/src/Spring/Spring.Core/Spring.Core.build b/src/Spring/Spring.Core/Spring.Core.build
index c61a140f..0df031d8 100644
--- a/src/Spring/Spring.Core/Spring.Core.build
+++ b/src/Spring/Spring.Core/Spring.Core.build
@@ -34,6 +34,7 @@
+
diff --git a/src/Spring/Spring.Core/Util/AttributeUtils.cs b/src/Spring/Spring.Core/Util/AttributeUtils.cs
index a63d4ec3..d4129cb2 100644
--- a/src/Spring/Spring.Core/Util/AttributeUtils.cs
+++ b/src/Spring/Spring.Core/Util/AttributeUtils.cs
@@ -1,6 +1,7 @@
using System;
+using System.Collections.Generic;
namespace Spring.Util
{
@@ -42,5 +43,46 @@ namespace Spring.Util
}
return FindAttribute(type.BaseType, attributeType);
}
+
+ ///
+ /// Get all attribute properties with values for a specific attribute type
+ ///
+ /// attribute to check against
+ /// collection of all properties with values
+ public static IDictionary GetAttributeProperties(Attribute attribute)
+ {
+ Type attributeType = attribute.GetType();
+ IDictionary attributes = new Dictionary();
+ foreach(var property in attributeType.GetProperties())
+ {
+ object value = property.GetValue(attribute, null);
+ attributes.Add(property.Name, value);
+ }
+ return attributes;
+ }
+
+ ///
+ /// Get the default name value of an attribute and a specific property
+ ///
+ /// attribute from where to get the default value
+ /// property to get the default value
+ ///
+ public static object GetDefaultValue(Attribute attribute, string propertyName)
+ {
+ Type attributeType = attribute.GetType();
+ try
+ {
+ var property = attributeType.GetProperty(propertyName);
+ if (property == null)
+ return null;
+ var instance = Activator.CreateInstance(attributeType);
+
+ return property.GetValue(instance, null);
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Util/IStringValueResolver.cs b/src/Spring/Spring.Core/Util/IStringValueResolver.cs
new file mode 100644
index 00000000..62e198e6
--- /dev/null
+++ b/src/Spring/Spring.Core/Util/IStringValueResolver.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Spring.Util
+{
+ ///
+ /// Simple strategy interface for resolving a String value.
+ ///
+ public interface IStringValueResolver
+ {
+ ///
+ /// Resolve the given String value, for example parsing placeholders.
+ ///
+ /// the original String value
+ /// the resolved String value
+ string ParseAndResolveVariables(string value);
+ }
+}
diff --git a/src/Spring/Spring.Core/Util/ObjectUtils.cs b/src/Spring/Spring.Core/Util/ObjectUtils.cs
index 3492872b..c2310083 100644
--- a/src/Spring/Spring.Core/Util/ObjectUtils.cs
+++ b/src/Spring/Spring.Core/Util/ObjectUtils.cs
@@ -412,6 +412,19 @@ namespace Spring.Util
return (o1 == o2 || (o1 != null && o1.Equals(o2)));
}
+
+ ///
+ /// Return as hash code for the given object; typically the value of
+ /// {@link Object#hashCode()}. If the object is an array,
+ /// this method will delegate to any of the nullSafeHashCode
+ /// methods for arrays in this class. If the object is null,
+ /// this method returns 0.
+ ///
+ public static int NullSafeHashCode(object o1)
+ {
+ return (o1 != null ? o1.GetHashCode() : 0);
+ }
+
///
/// Returns the first element in the supplied .
///
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeCollectionTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeCollectionTests.cs
deleted file mode 100644
index 41a87e30..00000000
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeCollectionTests.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-#region License
-
-/*
- * Copyright © 2002-2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#endregion
-
-using System.Collections.Generic;
-using NUnit.Framework;
-using Spring.Context.Support;
-using Spring.Objects.Factory.Config;
-using Spring.Objects.Factory.Support;
-
-namespace Spring.Objects.Factory.Attributes
-{
- [TestFixture]
- public class AutowireAttributeCollectionTests
- {
- private GenericApplicationContext _applicationContext;
-
- [SetUp]
- public void Setup()
- {
- _applicationContext = new GenericApplicationContext();
-
- var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
- objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
- _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
-
- objDef = new RootObjectDefinition(typeof(ColFoo1));
- _applicationContext.RegisterObjectDefinition("Foo1", objDef);
-
- objDef = new RootObjectDefinition(typeof(ColFoo2));
- _applicationContext.RegisterObjectDefinition("Foo2", objDef);
-
- objDef = new RootObjectDefinition(typeof(ColTestObject1));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("ColTestObject1", objDef);
-
- objDef = new RootObjectDefinition(typeof(ColTestObject2));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("ColTestObject2", objDef);
-
- objDef = new RootObjectDefinition(typeof(ColTestObject3));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("ColTestObject3", objDef);
-
- objDef = new RootObjectDefinition(typeof(ColTestObject4));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("ColTestObject4", objDef);
-
- _applicationContext.Refresh();
- }
-
- [Test]
- public void InjectAListOfObjects()
- {
- var testObj = (ColTestObject1)_applicationContext.GetObject("ColTestObject1");
- var objDef = _applicationContext.ObjectFactory.GetObjectDefinition("ColTestObject1");
-
- Assert.That(testObj.Count, Is.EqualTo(2));
- Assert.That(objDef.DependsOn.Count, Is.EqualTo(2));
- }
-
- [Test]
- public void InjectASetOfObjects()
- {
- var testObj = (ColTestObject2)_applicationContext.GetObject("ColTestObject2");
-
- Assert.That(testObj.Count, Is.EqualTo(2));
- }
-
- [Test]
- public void InjectADictionaryOfObjects()
- {
- var testObj = (ColTestObject3)_applicationContext.GetObject("ColTestObject3");
-
- Assert.That(testObj.Count, Is.EqualTo(2));
- }
-
- [Test]
- public void InjectAnArrayOfObjects()
- {
- var testObj = (ColTestObject4)_applicationContext.GetObject("ColTestObject4");
-
- Assert.That(testObj.Count, Is.EqualTo(2));
- }
- }
-
- #region Test Objects
-
- public interface IColFoo
- {
- string Name();
- }
-
- public class ColFoo1 : IColFoo
- {
- public string Name()
- {
- return "Foo1";
- }
- }
-
- public class ColFoo2 : IColFoo
- {
- public string Name()
- {
- return "Foo2";
- }
- }
-
- public class ColTestObject1
- {
- [Autowired]
- private IList _col;
-
- public int Count { get { return _col.Count; } }
- }
-
- public class ColTestObject2
- {
- [Autowired]
- private Spring.Collections.Generic.ISet _col;
-
- public int Count { get { return _col.Count; } }
- }
-
- public class ColTestObject3
- {
- [Autowired]
- private IDictionary _col;
-
- public int Count { get { return _col.Count; } }
- }
-
- public class ColTestObject4
- {
- [Autowired]
- private IColFoo[] _col;
-
- public int Count { get { return _col.Length; } }
- }
-
- #endregion
-
-}
\ No newline at end of file
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeConstructorTest.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeConstructorTest.cs
deleted file mode 100644
index f745c501..00000000
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeConstructorTest.cs
+++ /dev/null
@@ -1,343 +0,0 @@
-#region License
-
-/*
- * Copyright © 2002-2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using NUnit.Framework;
-using Spring.Context.Support;
-using Spring.Objects.Factory.Config;
-using Spring.Objects.Factory.Support;
-
-namespace Spring.Objects.Factory.Attributes
-{
- [TestFixture]
- public class AutowireAttributeConstructorTest
- {
- private GenericApplicationContext _applicationContext;
-
- [SetUp]
- public void Setup()
- {
- _applicationContext = new GenericApplicationContext();
-
- var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
- objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
- _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsSimple));
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsSimple", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsAdvanced));
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsAdvanced", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsHello));
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsHello", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsCiao));
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsCiao", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsTestObject1));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject1", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsTestObject2));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject2", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsTestObject3));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject3", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsTestObject4));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject4", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsTestObject5));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject5", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsTestObject6));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject6", objDef);
-
- objDef = new RootObjectDefinition(typeof(ConsTestObject7));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("ConsTestObject7", objDef);
-
- _applicationContext.Refresh();
- }
-
- [Test]
- public void ConstructorWithInjectParameter()
- {
- var testObj = (ConsTestObject1)_applicationContext.GetObject("ConsTestObject1");
-
- Assert.That(testObj.IsSet(), Is.True);
- }
-
- [Test]
- public void SelectInjectConstructorOverDefault()
- {
- var testObj = (ConsTestObject2)_applicationContext.GetObject("ConsTestObject2");
-
- Assert.That(testObj.IsSet(), Is.True);
- }
-
- [Test]
- public void SelectConstructorWithMostParamters()
- {
- var testObj = (ConsTestObject3)_applicationContext.GetObject("ConsTestObject3");
-
- Assert.That(testObj.IsSet(), Is.True);
- }
-
- [Test]
- public void FailIfParameterAreRequired()
- {
- Exception ex = null;
- try
- {
- var testObj = (ConsTestObject4)_applicationContext.GetObject("ConsTestObject4");
- }
- catch (Exception e) { ex = e; }
-
- Assert.That(ex, Is.Not.Null, "Exception should be thrown");
- Assert.That(ex.Message, Is.StringContaining("Unsatisfied dependency expressed"));
- }
-
- [Test]
- public void InjectCollection()
- {
- var testObj = (ConsTestObject5)_applicationContext.GetObject("ConsTestObject5");
-
- Assert.That(testObj.IsSet(), Is.True);
- Assert.That(testObj.ObjectCount(), Is.EqualTo(2));
- }
-
-
- [Test]
- public void SetParameterByParameterName()
- {
- var testObj = (ConsTestObject6)_applicationContext.GetObject("ConsTestObject6");
-
- Assert.That(testObj.IsSet(), Is.True);
- }
-
- [Test]
- public void SetParameterByQualifier()
- {
- var testObj = (ConsTestObject7)_applicationContext.GetObject("ConsTestObject7");
-
- Assert.That(testObj.IsSet(), Is.True);
- Assert.That(testObj.CorrectObject(), Is.True);
- }
- }
-
- #region Test Objects
-
- public interface IConsSimple
- {
- string Message();
- }
-
- public class ConsSimple : IConsSimple
- {
- public string Message()
- {
- return "ok";
- }
- }
-
- public interface IConsAdvanced
- {
- string Message();
- }
-
- public class ConsAdvanced : IConsAdvanced
- {
- public string Message()
- {
- return "ok";
- }
- }
-
- public interface INotSet
- {
- }
-
- public interface IConsCol
- {
- string Message();
- }
-
- public class ConsHello : IConsCol
- {
- public string Message()
- {
- return "hello";
- }
- }
-
- public class ConsCiao : IConsCol
- {
- public string Message()
- {
- return "ciao";
- }
- }
-
- public class ConsTestObject1
- {
- private IConsSimple _consSimple;
-
- [Autowired]
- public ConsTestObject1(IConsSimple consSimple)
- {
- _consSimple = consSimple;
- }
-
- public bool IsSet()
- {
- return _consSimple != null;
- }
- }
-
- public class ConsTestObject2
- {
- private IConsSimple _consSimple;
-
- public ConsTestObject2()
- {
- }
-
- [Autowired]
- public ConsTestObject2(IConsSimple consSimple)
- {
- _consSimple = consSimple;
- }
-
- public bool IsSet()
- {
- return _consSimple != null;
- }
- }
-
- public class ConsTestObject3
- {
- private IConsSimple _consSimple;
- private IConsAdvanced _consAdvanced;
-
- [Autowired(Required = false)]
- public ConsTestObject3(IConsSimple consSimple)
- {
- _consSimple = consSimple;
- }
-
- [Autowired(Required = false)]
- public ConsTestObject3(IConsSimple consSimple, IConsAdvanced consAdvanced)
- {
- _consSimple = consSimple;
- _consAdvanced = consAdvanced;
- }
-
- public bool IsSet()
- {
- return _consSimple != null && _consAdvanced != null;
- }
- }
-
- public class ConsTestObject4
- {
- private INotSet _notSet;
-
- [Autowired]
- public ConsTestObject4(INotSet notSet)
- {
- _notSet = notSet;
- }
-
- public bool IsSet()
- {
- return _notSet != null;
- }
- }
-
- public class ConsTestObject5
- {
- private IDictionary _consCol;
-
- [Autowired]
- public ConsTestObject5(IDictionary consCol)
- {
- _consCol = consCol;
- }
-
- public bool IsSet()
- {
- return _consCol != null;
- }
-
- public int ObjectCount()
- {
- return _consCol.Count;
- }
- }
-
- public class ConsTestObject6
- {
- private IConsCol _consHello;
-
- [Autowired]
- public ConsTestObject6(IConsCol consHello)
- {
- _consHello = consHello;
- }
-
- public bool IsSet()
- {
- return _consHello != null;
- }
- }
-
- public class ConsTestObject7
- {
- private IConsCol _consHello;
-
- [Autowired]
- public ConsTestObject7([Qualifier("ConsCiao")] IConsCol consHello)
- {
- _consHello = consHello;
- }
-
- public bool IsSet()
- {
- return _consHello != null;
- }
-
- public bool CorrectObject()
- {
- return _consHello.Message() == "ciao";
- }
- }
-
- #endregion
-}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeFieldTest.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeFieldTest.cs
deleted file mode 100644
index b9fc2c29..00000000
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeFieldTest.cs
+++ /dev/null
@@ -1,290 +0,0 @@
-#region License
-
-/*
- * Copyright 2002-2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#endregion
-
-using System;
-using NUnit.Framework;
-using Spring.Context.Support;
-using Spring.Objects.Factory.Config;
-using Spring.Objects.Factory.Support;
-
-namespace Spring.Objects.Factory.Attributes
-{
- [TestFixture]
- public class AutowireAttributeFieldTest
- {
- private GenericApplicationContext _applicationContext;
-
- [SetUp]
- public void Setup()
- {
- _applicationContext = new GenericApplicationContext();
-
- var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
- objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
- _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
-
-
- objDef = new RootObjectDefinition(typeof(FldFooImpl));
- _applicationContext.RegisterObjectDefinition("FldFoo", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldHello));
- _applicationContext.RegisterObjectDefinition("FldHello", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldCioa));
- _applicationContext.RegisterObjectDefinition("FldCioa", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldHola));
- _applicationContext.RegisterObjectDefinition("FldHola", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldTestObject1));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("FldTestObject1", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldTestObject2));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("FldTestObject2", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldTestObject3));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("FldTestObject3", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldTestObject4));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("FldTestObject4", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldTestObject5));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("FldTestObject5", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldTestObject6));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("FldTestObject6", objDef);
-
- objDef = new RootObjectDefinition(typeof(FldTestObject7));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("FldTestObject7", objDef);
-
- _applicationContext.Refresh();
- }
-
- [Test]
- public void InjectPropertyBasedOnFieldType()
- {
- var testObj = (FldTestObject1)_applicationContext.GetObject("FldTestObject1");
- var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("FldTestObject1");
-
- Assert.That(testObj.Test(), Is.EqualTo("foo"));
- Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
- }
-
- [Test]
- public void WithTwoTypesRegisteredAndNoNameShouldFail()
- {
- Assert.That(delegate { var testObj = (FldTestObject2)_applicationContext.GetObject("FldTestObject2"); }, Throws.Exception.TypeOf());
- }
-
- [Test]
- public void WithQualifierName()
- {
- var testObj = (FldTestObject3)_applicationContext.GetObject("FldTestObject3");
-
- Assert.That(testObj.Say(), Is.EqualTo("cioa"));
- }
-
- [Test]
- public void WithTwoTypesAndNoQualifierUsePopertyName()
- {
- var testObj = (FldTestObject4)_applicationContext.GetObject("FldTestObject4");
-
- Assert.That(testObj.Say(), Is.EqualTo("cioa"));
- }
-
- [Test]
- public void FailIfTypeCantBeResolved()
- {
- Exception ex = null;
- try
- {
- var testObj = (FldTestObject5)_applicationContext.GetObject("FldTestObject5");
- }
- catch (Exception e) { ex = e; }
-
- Assert.That(ex, Is.Not.Null, "Should throw an exception");
- Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
- }
-
- [Test]
- public void InjectedObjectAssignedToTwoInterfaces()
- {
- var testObj = (FldTestObject6)_applicationContext.GetObject("FldTestObject6");
-
- Assert.That(testObj.Test(), Is.EqualTo("test"));
- }
-
- [Test]
- public void IsNotRequired()
- {
- var testObj = (FldTestObject7)_applicationContext.GetObject("FldTestObject7");
-
- Assert.That(testObj.IsNull(), Is.True);
- }
-
- }
-
-
- #region Test Objects
-
- public interface IFldNotAnObject
- {
-
- }
-
- public interface IFldAnotherOne
- {
- string Quite();
- }
-
- public interface IFldFoo
- {
- string Test();
- }
-
- public class FldFooImpl : IFldFoo
- {
- public string Test()
- {
- return "foo";
- }
- }
-
- public interface IFldSay
- {
- string Say();
- }
-
- public class FldHello : IFldSay
- {
- public string Say()
- {
- return "hello";
- }
- }
-
- public class FldCioa : IFldSay
- {
- public string Say()
- {
- return "cioa";
- }
- }
-
- public class FldHola : IFldFoo, IFldAnotherOne
- {
- public string Quite()
- {
- return "test";
- }
-
- public string Test()
- {
- return "test";
- }
- }
-
- public class FldTestObject1
- {
- [Autowired]
- private IFldFoo _fldFoo;
-
- public string Test()
- {
- return _fldFoo.Test();
- }
- }
-
- // object with 2 possibilities should fail
- public class FldTestObject2
- {
- [Autowired]
- private IFldSay _wrongName;
-
- public string Say()
- {
- return _wrongName.Say();
- }
- }
-
- // should not fail but inject Cioa object
- public class FldTestObject3
- {
- [Autowired]
- [Qualifier("FldCioa")]
- private IFldSay _fldCioa;
-
- public string Say()
- {
- return _fldCioa.Say();
- }
- }
-
- // should not fail but inject Hello via Propertyname
- public class FldTestObject4
- {
- [Autowired]
- private IFldSay _fldCioa;
-
- public string Say()
- {
- return _fldCioa.Say();
- }
- }
-
- // should not fail but inject Hello via Propertyname
- public class FldTestObject5
- {
- [Autowired]
- private IFldNotAnObject _ohhh;
- }
-
- public class FldTestObject6
- {
- [Autowired]
- private IFldAnotherOne _hola;
-
- public string Test()
- {
- return _hola.Quite();
- }
- }
-
- public class FldTestObject7
- {
- [Autowired(Required = false)]
- private IFldNotAnObject _nono;
-
- public bool IsNull()
- {
- return (_nono == null);
- }
- }
-
- #endregion
-
-}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeMethodsTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeMethodsTests.cs
deleted file mode 100644
index 8d0bd0b5..00000000
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributeMethodsTests.cs
+++ /dev/null
@@ -1,371 +0,0 @@
-#region License
-
-/*
- * Copyright © 2002-2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using NUnit.Framework;
-using Spring.Context.Support;
-using Spring.Objects.Factory.Config;
-using Spring.Objects.Factory.Support;
-
-namespace Spring.Objects.Factory.Attributes
-{
- [TestFixture]
- public class AutowireAttributeMethodsTests
- {
- private GenericApplicationContext _applicationContext;
-
- [SetUp]
- public void Setup()
- {
- _applicationContext = new GenericApplicationContext();
-
- var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
- objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
- _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
-
- objDef = new RootObjectDefinition(typeof(Simple));
- _applicationContext.ObjectFactory.RegisterObjectDefinition("Simple", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodHello));
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodHello", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodCiao));
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodCiao", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject1));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject1", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject2));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject2", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject3));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject3", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject4));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject4", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject5));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject5", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject6));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject6", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject7));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject7", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject8));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject8", objDef);
-
- objDef = new RootObjectDefinition(typeof(MethodTestObject9));
- objDef.Scope = "prototype";
- _applicationContext.ObjectFactory.RegisterObjectDefinition("MethodTestObject9", objDef);
-
- _applicationContext.Refresh();
- }
-
- [Test]
- public void InObjectByType()
- {
- var testObj = (MethodTestObject1)_applicationContext.GetObject("MethodTestObject1");
- var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("MethodTestObject1");
-
- Assert.That(testObj.GetObject(), Is.Not.Null);
- Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
- }
-
- [Test]
- public void InjectByParamterName()
- {
- var testObj = (MethodTestObject2)_applicationContext.GetObject("MethodTestObject2");
-
- Assert.That(testObj.GetObject(), Is.Not.Null);
- }
-
- [Test]
- public void InjectByQualifier()
- {
- var testObj = (MethodTestObject3)_applicationContext.GetObject("MethodTestObject3");
-
- Assert.That(testObj.GetObject(), Is.Not.Null);
- }
-
- [Test]
- public void FailIfTypeCantBeResolved()
- {
- Exception ex = null;
- try
- {
- var testObj = (FldTestObject5)_applicationContext.GetObject("MethodTestObject4");
- }
- catch (Exception e) { ex = e; }
-
- Assert.That(ex, Is.Not.Null, "Should throw an exception");
- Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
- }
-
- [Test]
- public void InjectListOfObjects()
- {
- var testObj = (MethodTestObject5)_applicationContext.GetObject("MethodTestObject5");
-
- Assert.That(testObj.GetObject(), Is.Not.Null);
- Assert.That(testObj.GetObject().Count, Is.EqualTo(2));
- }
-
- [Test]
- public void InjectSeveralParameters()
- {
- var testObj = (MethodTestObject6)_applicationContext.GetObject("MethodTestObject6");
- var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("MethodTestObject6");
-
- Assert.That(testObj.GetObject(), Is.Not.Null);
- Assert.That(testObj.GetSimple(), Is.Not.Null);
- Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(2));
- }
-
- [Test]
- public void FailIfObjecNotAvailable()
- {
- Assert.That(delegate { var testObj = (MethodTestObject7)_applicationContext.GetObject("MethodTestObject7"); },
- Throws.Exception.TypeOf());
- }
-
- [Test]
- public void PassIfObjectNotavailableButNotRequired()
- {
- var testObj1 = (MethodTestObject8)_applicationContext.GetObject("MethodTestObject8");
- var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("MethodTestObject8");
-
- Assert.That(testObj1.GetSimple(), Is.Null);
- Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
-
- var testObj2 = (MethodTestObject9)_applicationContext.GetObject("MethodTestObject9");
- objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("MethodTestObject9");
-
- Assert.That(testObj2.GetrAdvanced(), Is.Null);
- Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
- }
-
- }
-
-
- #region Test Objects
-
- public interface ISimple
- {
- string Foo();
- }
-
- public class Simple : ISimple
- {
- public string Foo()
- {
- return "simple";
- }
- }
-
- public interface IAdvanced
- {
-
- }
-
- public interface IMethodFoo
- {
- string Foo();
- }
-
- public class MethodHello : IMethodFoo
- {
- public string Foo()
- {
- return "hello";
- }
- }
-
- public class MethodCiao : IMethodFoo
- {
- public string Foo()
- {
- return "ciao";
- }
- }
-
- public class MethodTestObject1
- {
- private ISimple _impl;
-
- [Autowired]
- public void Prepare(ISimple impl)
- {
- _impl = impl;
- }
-
- public object GetObject()
- {
- return _impl;
- }
- }
-
- public class MethodTestObject2
- {
- private IMethodFoo _methodCiao;
-
- [Autowired]
- public void Prepare(IMethodFoo methodCiao)
- {
- _methodCiao = methodCiao;
- }
-
- public object GetObject()
- {
- return _methodCiao;
- }
- }
-
- public class MethodTestObject3
- {
- private IMethodFoo _impl;
-
- [Autowired]
- public void Prepare([Qualifier("MethodHello")] IMethodFoo impl)
- {
- _impl = impl;
- }
-
- public object GetObject()
- {
- return _impl;
- }
- }
-
- public class MethodTestObject4
- {
- private IMethodFoo _impl;
-
- [Autowired]
- public void Prepare([Qualifier("MethodHello")] IMethodFoo impl, string test)
- {
- _impl = impl;
- }
-
- public object GetObject()
- {
- return _impl;
- }
- }
-
- public class MethodTestObject5
- {
- private IList _impl;
-
- [Autowired]
- public void Prepare(IList impl)
- {
- _impl = impl;
- }
-
- public IList GetObject()
- {
- return _impl;
- }
- }
-
- public class MethodTestObject6
- {
- private IMethodFoo _impl;
- private ISimple _simple;
-
- [Autowired]
- public void Prepare(IMethodFoo methodHello, ISimple simple)
- {
- _impl = methodHello;
- _simple = simple;
- }
-
- public object GetObject()
- {
- return _impl;
- }
-
- public object GetSimple()
- {
- return _simple;
- }
- }
-
- public class MethodTestObject7
- {
- private ISimple _simple;
-
- [Autowired]
- public void Prepare([Qualifier("NotAvailable")] ISimple simple)
- {
- _simple = simple;
- }
-
- public object GetSimple()
- {
- return _simple;
- }
- }
-
- public class MethodTestObject8
- {
- private ISimple _simple;
-
- [Autowired(Required = false)]
- public void Prepare([Qualifier("NotAvailable")] ISimple simple)
- {
- _simple = simple;
- }
-
- public object GetSimple()
- {
- return _simple;
- }
- }
-
- public class MethodTestObject9
- {
- private IAdvanced _advanced;
-
- [Autowired(Required = false)]
- public void Prepare(IAdvanced advanced)
- {
- _advanced = advanced;
- }
-
- public object GetrAdvanced()
- {
- return _advanced;
- }
- }
-
- #endregion
-}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributePropertyTest.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributePropertyTest.cs
deleted file mode 100644
index eec2e459..00000000
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireAttributePropertyTest.cs
+++ /dev/null
@@ -1,254 +0,0 @@
-#region License
-
-/*
- * Copyright © 2002-2011 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#endregion
-
-using System;
-using NUnit.Framework;
-using Spring.Context.Support;
-using Spring.Objects.Factory.Config;
-using Spring.Objects.Factory.Support;
-
-namespace Spring.Objects.Factory.Attributes
-{
- [TestFixture]
- public class AutowireAttributePropertyTest
- {
- private GenericApplicationContext _applicationContext;
-
- [SetUp]
- public void Setup()
- {
- _applicationContext = new GenericApplicationContext();
-
- var objDef = new RootObjectDefinition(typeof(AutowiredAttributeObjectPostProcessor));
- objDef.Role = ObjectRole.ROLE_INFRASTRUCTURE;
- _applicationContext.RegisterObjectDefinition("AutowiredAttributeObjectPostProcessor", objDef);
-
-
- objDef = new RootObjectDefinition(typeof(PropFooImpl));
- _applicationContext.RegisterObjectDefinition("PropFoo", objDef);
-
- objDef = new RootObjectDefinition(typeof(PropHello));
- _applicationContext.RegisterObjectDefinition("PropHello", objDef);
-
- objDef = new RootObjectDefinition(typeof(PropCioa));
- _applicationContext.RegisterObjectDefinition("PropCioa", objDef);
-
- objDef = new RootObjectDefinition(typeof(PropTestObject1));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("PropTestObject1", objDef);
-
- objDef = new RootObjectDefinition(typeof(PropTestObject2));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("PropTestObject2", objDef);
-
- objDef = new RootObjectDefinition(typeof(PropTestObject3));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("PropTestObject3", objDef);
-
- objDef = new RootObjectDefinition(typeof(PropTestObject4));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("PropTestObject4", objDef);
-
- objDef = new RootObjectDefinition(typeof(PropTestObject5));
- objDef.Scope = "prototype";
- _applicationContext.RegisterObjectDefinition("PropTestObject5", objDef);
-
- _applicationContext.Refresh();
- }
-
- [Test]
- public void InjectPropertyBasedOnPropertyType()
- {
- var testObj = (PropTestObject1)_applicationContext.GetObject("PropTestObject1");
- var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("PropTestObject1");
-
- Assert.That(testObj.Foo, Is.Not.Null);
- Assert.That(testObj.Test(), Is.EqualTo("foo"));
- Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1), "Should have one Dependant Object");
- }
-
- [Test]
- public void WithTwoTypesRegisteredAndNoNameShouldFail()
- {
- Assert.That(delegate { var testObj = (PropTestObject2)_applicationContext.GetObject("PropTestObject2"); }, Throws.Exception.TypeOf());
- }
-
- [Test]
- public void WithQualifierName()
- {
- var testObj = (PropTestObject3)_applicationContext.GetObject("PropTestObject3");
-
- Assert.That(testObj.Cioa, Is.Not.Null);
- Assert.That(testObj.Say(), Is.EqualTo("cioa"));
- }
-
- [Test]
- public void WithTwoTypesAndNoQualifierUsePopertyName()
- {
- var testObj = (PropTestObject4)_applicationContext.GetObject("PropTestObject4");
-
- Assert.That(testObj.PropCioa, Is.Not.Null);
- Assert.That(testObj.Say(), Is.EqualTo("cioa"));
- }
-
- [Test]
- public void FailIfTypeCantBeResolved()
- {
- Exception ex = null;
- try
- {
- var testObj = (FldTestObject5)_applicationContext.GetObject("PropTestObject5");
- }
- catch (Exception e) { ex = e; }
-
- Assert.That(ex, Is.Not.Null, "Should throw an exception");
- Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
- }
-
- }
-
- #region Test Objects
-
- public interface IPropNotAnObject
- {
-
- }
-
- public interface IPropFoo
- {
- string Test();
- }
-
- public class PropFooImpl : IPropFoo
- {
- public string Test()
- {
- return "foo";
- }
- }
-
- public interface IPropSay
- {
- string PropSay();
- }
-
- public class PropHello : IPropSay
- {
- public string PropSay()
- {
- return "hello";
- }
- }
-
- public class PropCioa : IPropSay
- {
- public string PropSay()
- {
- return "cioa";
- }
- }
-
- public class PropTestObject1
- {
- private IPropFoo _foo;
-
- [Autowired]
- public IPropFoo Foo
- {
- get { return _foo; }
- set { _foo = value; }
- }
-
- public string Test()
- {
- return _foo.Test();
- }
- }
-
- public class PropTestObject2
- {
- private IPropSay _hello;
-
- [Autowired]
- public IPropSay WrongName
- {
- get { return _hello; }
- set { _hello = value; }
- }
-
- public string Say()
- {
- return _hello.PropSay();
- }
- }
-
- // should not fail but inject Cioa object
- public class PropTestObject3
- {
- private IPropSay _cioa;
-
- [Autowired]
- [Qualifier("PropCioa")]
- public IPropSay Cioa
- {
- get { return _cioa; }
- set { _cioa = value; }
- }
-
- public string Say()
- {
- return _cioa.PropSay();
- }
- }
-
- // should not fail but inject Hello via Propertyname
- public class PropTestObject4
- {
- private IPropSay _obj;
-
- [Autowired]
- public IPropSay PropCioa
- {
- get { return _obj; }
- set { _obj = value; }
- }
-
- public string Say()
- {
- return _obj.PropSay();
- }
- }
-
- // should not fail but inject Hello via Propertyname
- public class PropTestObject5
- {
- private IPropNotAnObject _obj;
-
- [Autowired]
- public IPropNotAnObject Ohhh
- {
- get { return _obj; }
- set { _obj = value; }
- }
- }
-
- #endregion
-
-}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByQualifierAttributeTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByQualifierAttributeTests.cs
new file mode 100644
index 00000000..c49e3a1e
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByQualifierAttributeTests.cs
@@ -0,0 +1,87 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Attributes.ByType;
+using AutowireTestConstructorNormal = Spring.Objects.Factory.Attributes.ByQualifierAttribute.AutowireTestConstructorNormal;
+using AutowireTestFieldNormal = Spring.Objects.Factory.Attributes.ByQualifierAttribute.AutowireTestFieldNormal;
+using AutowireTestMethodNormal = Spring.Objects.Factory.Attributes.ByQualifierAttribute.AutowireTestMethodNormal;
+using AutowireTestPropertyNormal = Spring.Objects.Factory.Attributes.ByQualifierAttribute.AutowireTestPropertyNormal;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireByQualifierAttributeTests
+ {
+ private XmlApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new XmlApplicationContext(false,
+ "assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/ByQualifierAttributeObjects.xml");
+ }
+
+ [Test]
+ public void InjectOnField()
+ {
+ var testObj = (AutowireTestFieldNormal) _applicationContext.GetObject("AutowireTestField");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestField");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(testObj.ciao.GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnProperty()
+ {
+ var testObj = (AutowireTestPropertyNormal) _applicationContext.GetObject("AutowireTestProperty");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestProperty");
+
+ Assert.That(testObj.Ciao, Is.Not.Null);
+ Assert.That(testObj.Ciao.GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnMethod()
+ {
+ var testObj = (AutowireTestMethodNormal) _applicationContext.GetObject("AutowireTestMethod");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestMethod");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(testObj.ciao.GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnConstructor()
+ {
+ var testObj = (AutowireTestConstructorNormal)_applicationContext.GetObject("AutowireTestConstructor");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestConstructor");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(testObj.ciao.GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+ }
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByQualifierTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByQualifierTests.cs
new file mode 100644
index 00000000..b4ec6c5d
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByQualifierTests.cs
@@ -0,0 +1,87 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Attributes.ByType;
+using AutowireTestConstructorNormal = Spring.Objects.Factory.Attributes.ByQualifier.AutowireTestConstructorNormal;
+using AutowireTestFieldNormal = Spring.Objects.Factory.Attributes.ByQualifier.AutowireTestFieldNormal;
+using AutowireTestMethodNormal = Spring.Objects.Factory.Attributes.ByQualifier.AutowireTestMethodNormal;
+using AutowireTestPropertyNormal = Spring.Objects.Factory.Attributes.ByQualifier.AutowireTestPropertyNormal;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireByQualifierTests
+ {
+ private XmlApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new XmlApplicationContext(false,
+ "assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/ByQualifierObjects.xml");
+ }
+
+ [Test]
+ public void InjectOnField()
+ {
+ var testObj = (AutowireTestFieldNormal) _applicationContext.GetObject("AutowireTestField");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestField");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(testObj.ciao.GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnProperty()
+ {
+ var testObj = (AutowireTestPropertyNormal) _applicationContext.GetObject("AutowireTestProperty");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestProperty");
+
+ Assert.That(testObj.Ciao, Is.Not.Null);
+ Assert.That(testObj.Ciao.GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnMethod()
+ {
+ var testObj = (AutowireTestMethodNormal) _applicationContext.GetObject("AutowireTestMethod");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestMethod");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(testObj.ciao.GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnConstructor()
+ {
+ var testObj = (AutowireTestConstructorNormal)_applicationContext.GetObject("AutowireTestConstructor");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestConstructor");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(testObj.ciao.GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+ }
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeFailTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeFailTests.cs
new file mode 100644
index 00000000..de6b92ce
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeFailTests.cs
@@ -0,0 +1,98 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Attributes.ByType;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireByTypeFailTests
+ {
+ private XmlApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new XmlApplicationContext(false,
+ "assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/ByTypeFailObjects.xml");
+ }
+
+ [Test]
+ public void FailFieldInjectionTooManyObjects()
+ {
+ Exception ex = null;
+ try
+ {
+ var testObj = (AutowireTestFieldNormal)_applicationContext.GetObject("AutowireTestFieldNormal");
+ }
+ catch (Exception e) { ex = e; }
+
+ Assert.That(ex, Is.Not.Null, "Should throw an exception");
+ Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
+ }
+
+ [Test]
+ public void FailPropertyInjectionTooManyObjects()
+ {
+ Exception ex = null;
+ try
+ {
+ var testObj = (AutowireTestPropertyNormal)_applicationContext.GetObject("AutowireTestPropertyNormal");
+ }
+ catch (Exception e) { ex = e; }
+
+ Assert.That(ex, Is.Not.Null, "Should throw an exception");
+ Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
+ }
+
+ [Test]
+ public void FailMethodInjectionTooManyObjects()
+ {
+ Exception ex = null;
+ try
+ {
+ var testObj = (AutowireTestMethodNormal)_applicationContext.GetObject("AutowireTestMethodNormal");
+ }
+ catch (Exception e) { ex = e; }
+
+ Assert.That(ex, Is.Not.Null, "Should throw an exception");
+ Assert.That(ex.Message, Is.StringContaining("Injection of autowired dependencies failed"));
+ }
+
+ [Test]
+ public void FailConstructorInjectionTooManyObjects()
+ {
+ Exception ex = null;
+ try
+ {
+ var testObj = (AutowireTestConstructorNormal)_applicationContext.GetObject("AutowireTestConstructorNormal");
+ }
+ catch (Exception e) { ex = e; }
+
+ Assert.That(ex, Is.Not.Null, "Should throw an exception");
+ Assert.That(ex.Message, Is.StringContaining("Error creating object with name"));
+ }
+ }
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeNormalTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeNormalTests.cs
new file mode 100644
index 00000000..d46d965c
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeNormalTests.cs
@@ -0,0 +1,82 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Attributes.ByType;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireByTypeNormalTests
+ {
+ private XmlApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new XmlApplicationContext(false,
+ "assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/ByTypeNormalObjects.xml");
+ }
+
+ [Test]
+ public void InjectOnField()
+ {
+ var testObj = (AutowireTestFieldNormal) _applicationContext.GetObject("AutowireTestFieldNormal");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestFieldNormal");
+
+ Assert.That(testObj.hello, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnProperty()
+ {
+ var testObj = (AutowireTestPropertyNormal) _applicationContext.GetObject("AutowireTestPropertyNormal");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestPropertyNormal");
+
+ Assert.That(testObj.Hello, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnMethod()
+ {
+ var testObj = (AutowireTestMethodNormal) _applicationContext.GetObject("AutowireTestMethodNormal");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestMethodNormal");
+
+ Assert.That(testObj.hello, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnConstructor()
+ {
+ var testObj = (AutowireTestConstructorNormal)_applicationContext.GetObject("AutowireTestConstructorNormal");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestConstructorNormal");
+
+ Assert.That(testObj.hello, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+ }
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeNotRequiredTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeNotRequiredTests.cs
new file mode 100644
index 00000000..6a849827
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypeNotRequiredTests.cs
@@ -0,0 +1,72 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Attributes.ByType;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireByTypeNotRequiredTests
+ {
+ private XmlApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new XmlApplicationContext(false,
+ "assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/ByTypeNotRequiredObjects.xml");
+ }
+
+ [Test]
+ public void InjectOnField()
+ {
+ var testObj = (AutowireTestFieldNotRequired) _applicationContext.GetObject("AutowireTestField");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestField");
+
+ Assert.That(testObj.hello, Is.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void InjectOnProperty()
+ {
+ var testObj = (AutowireTestPropertyNotRequired) _applicationContext.GetObject("AutowireTestProperty");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestProperty");
+
+ Assert.That(testObj.Hello, Is.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void InjectOnMethod()
+ {
+ var testObj = (AutowireTestMethodNotRequired) _applicationContext.GetObject("AutowireTestMethod");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestMethod");
+
+ Assert.That(testObj.hello, Is.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+ }
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypePrimaryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypePrimaryTests.cs
new file mode 100644
index 00000000..c3899321
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByTypePrimaryTests.cs
@@ -0,0 +1,82 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Attributes.ByType;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireByTypePrimaryTests
+ {
+ private XmlApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new XmlApplicationContext(false,
+ "assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/ByTypePrimaryObjects.xml");
+ }
+
+ [Test]
+ public void InjectOnField()
+ {
+ var testObj = (AutowireTestFieldNormal) _applicationContext.GetObject("AutowireTestFieldNormal");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestFieldNormal");
+
+ Assert.That(testObj.hello, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnProperty()
+ {
+ var testObj = (AutowireTestPropertyNormal) _applicationContext.GetObject("AutowireTestPropertyNormal");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestPropertyNormal");
+
+ Assert.That(testObj.Hello, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnMethod()
+ {
+ var testObj = (AutowireTestMethodNormal) _applicationContext.GetObject("AutowireTestMethodNormal");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestMethodNormal");
+
+ Assert.That(testObj.hello, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void InjectOnConstructor()
+ {
+ var testObj = (AutowireTestConstructorNormal)_applicationContext.GetObject("AutowireTestConstructorNormal");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestConstructorNormal");
+
+ Assert.That(testObj.hello, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+ }
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByValueTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByValueTests.cs
new file mode 100644
index 00000000..24519012
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireByValueTests.cs
@@ -0,0 +1,96 @@
+#region License
+
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System.Collections.Specialized;
+using NUnit.Framework;
+using Spring.Context;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Attributes.ByValue;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireByValueTests
+ {
+ private XmlApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new XmlApplicationContext(false, "assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/ByValueObjects.xml");
+ ContextRegistry.RegisterContext(_applicationContext);
+ }
+
+ [TearDown]
+ public void Dispose()
+ {
+ ContextRegistry.Clear();
+ }
+
+ [Test]
+ public void InjectOnField()
+ {
+ var testObj = (AutowireTestFieldNormal) _applicationContext.GetObject("AutowireTestField");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestField");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void InjectOnProperty()
+ {
+ var testObj = (AutowireTestPropertyNormal) _applicationContext.GetObject("AutowireTestProperty");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestProperty");
+
+ Assert.That(testObj.Ciao, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void InjectOnMethod()
+ {
+ var testObj = (AutowireTestMethodNormal) _applicationContext.GetObject("AutowireTestMethod");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestMethod");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void InjectOnConstructor()
+ {
+ var testObj = (AutowireTestConstructorNormal)_applicationContext.GetObject("AutowireTestConstructor");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestConstructor");
+
+ Assert.That(testObj.ciao, Is.Not.Null);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void InjectPropertyPlaceholderValue()
+ {
+ var testObj = (AutowireTestPropertyPlaceHolder)_applicationContext.GetObject("AutowireTestPropertyPlaceHolder");
+ Assert.That(testObj.greeting, Is.EqualTo("ciao"));
+ }
+ }
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireCollectionTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireCollectionTests.cs
new file mode 100644
index 00000000..14bc85d3
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireCollectionTests.cs
@@ -0,0 +1,106 @@
+#region License
+
+/*
+ * Copyright © 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+using System;
+using NUnit.Framework;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Attributes.ByType;
+using Spring.Objects.Factory.Attributes.Collections;
+
+namespace Spring.Objects.Factory.Attributes
+{
+ [TestFixture]
+ public class AutowireCollectionTests
+ {
+ private XmlApplicationContext _applicationContext;
+
+ [SetUp]
+ public void Setup()
+ {
+ _applicationContext = new XmlApplicationContext(false,
+ "assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/CollectionObjects.xml");
+ }
+
+ [Test]
+ public void InjectIntoList()
+ {
+ var testObj = (AutowireTestList)_applicationContext.GetObject("AutowireTestList");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestList");
+
+ Assert.That(testObj.foos, Is.Not.Null);
+ Assert.That(testObj.foos.Count, Is.EqualTo(2));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void InjectIntoSet()
+ {
+ var testObj = (AutowireTestSet)_applicationContext.GetObject("AutowireTestSet");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestSet");
+
+ Assert.That(testObj.foos, Is.Not.Null);
+ Assert.That(testObj.foos.Count, Is.EqualTo(2));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void InjectIntoDictionary()
+ {
+ var testObj = (AutowireTestDictionary)_applicationContext.GetObject("AutowireTestDictionary");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestDictionary");
+
+ Assert.That(testObj.foos, Is.Not.Null);
+ Assert.That(testObj.foos.Count, Is.EqualTo(2));
+ Assert.That(testObj.foos.ContainsKey("HelloFoo"), Is.True);
+ Assert.That(testObj.foos.ContainsKey("CiaoFoo"), Is.True);
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void InjectIntoDictionaryFail()
+ {
+ Exception ex = null;
+
+ try
+ {
+ var testObj = (AutowireTestDictionaryFail)_applicationContext.GetObject("AutowireTestDictionaryFail");
+ }
+ catch (Exception e)
+ {
+ ex = e;
+ }
+
+ Assert.That(ex, Is.Not.Null);
+ Assert.That(ex.InnerException.InnerException.Message.Contains("first generic to be a string"), Is.True);
+ }
+
+ [Test]
+ public void InjectIntoListWithQualifier()
+ {
+ var testObj = (AutowireTestQualifier)_applicationContext.GetObject("AutowireTestQualifier");
+ var objectDefinition = _applicationContext.ObjectFactory.GetObjectDefinition("AutowireTestQualifier");
+
+ Assert.That(testObj.foos, Is.Not.Null);
+ Assert.That(testObj.foos.Count, Is.EqualTo(1));
+ Assert.That(testObj.foos[0].GetType(), Is.EqualTo(typeof(CiaoFoo)));
+ Assert.That(objectDefinition.DependsOn.Count, Is.EqualTo(1));
+ }
+ }
+}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireTestObjects.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireTestObjects.cs
new file mode 100644
index 00000000..d5b099a7
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/AutowireTestObjects.cs
@@ -0,0 +1,252 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Spring.Objects.Factory.Attributes.ByType;
+
+namespace Spring.Objects.Factory.Attributes.ByType
+{
+ public interface IFoo
+ {
+ string Say();
+ }
+
+ public class HelloFoo : IFoo
+ {
+ public string Say()
+ {
+ return "hello";
+ }
+ }
+
+ public class CiaoFoo : IFoo
+ {
+ public string Say()
+ {
+ return "ciao";
+ }
+ }
+
+ public class AutowireTestFieldNormal
+ {
+ [Autowired]
+ public IFoo hello;
+ }
+
+ public class AutowireTestPropertyNormal
+ {
+ [Autowired]
+ public IFoo Hello { get; set; }
+ }
+
+ public class AutowireTestMethodNormal
+ {
+ public IFoo hello;
+
+ [Autowired]
+ private void Prepare(IFoo hello)
+ {
+ this.hello = hello;
+ }
+ }
+
+ public class AutowireTestConstructorNormal
+ {
+ public IFoo hello;
+
+ [Autowired]
+ public AutowireTestConstructorNormal(IFoo hello)
+ {
+ this.hello = hello;
+ }
+ }
+
+ public class AutowireTestFieldNotRequired
+ {
+ [Autowired(Required = false)]
+ public IFoo hello;
+ }
+
+ public class AutowireTestPropertyNotRequired
+ {
+ [Autowired(Required = false)]
+ public IFoo Hello { get; set; }
+ }
+
+ public class AutowireTestMethodNotRequired
+ {
+ public IFoo hello;
+
+ [Autowired(Required = false)]
+ private void Prepare(IFoo hello)
+ {
+ this.hello = hello;
+ }
+ }
+
+}
+
+namespace Spring.Objects.Factory.Attributes.ByQualifier
+{
+ public class AutowireTestFieldNormal
+ {
+ [Autowired]
+ [Qualifier("ciao")]
+ public IFoo ciao;
+ }
+
+ public class AutowireTestPropertyNormal
+ {
+ [Autowired]
+ [Qualifier("ciao")]
+ public IFoo Ciao { get; set; }
+ }
+
+ public class AutowireTestMethodNormal
+ {
+ public IFoo ciao;
+
+ [Autowired]
+ private void Prepare([Qualifier("ciao")] IFoo ciao)
+ {
+ this.ciao = ciao;
+ }
+ }
+
+ public class AutowireTestConstructorNormal
+ {
+ public IFoo ciao;
+
+ [Autowired]
+ public AutowireTestConstructorNormal([Qualifier("ciao")] IFoo ciao)
+ {
+ this.ciao = ciao;
+ }
+ }
+}
+
+namespace Spring.Objects.Factory.Attributes.ByQualifierAttribute
+{
+ public class DialectAttribute : QualifierAttribute
+ {
+ private string _language = "";
+
+ public string Language { get { return _language; } set { _language = value; } }
+ }
+
+ public class AutowireTestFieldNormal
+ {
+ [Autowired]
+ [Dialect(Language = "Italian")]
+ public IFoo ciao;
+ }
+
+ public class AutowireTestPropertyNormal
+ {
+ [Autowired]
+ [Dialect(Language = "Italian")]
+ public IFoo Ciao { get; set; }
+ }
+
+ public class AutowireTestMethodNormal
+ {
+ public IFoo ciao;
+
+ [Autowired]
+ private void Prepare([Dialect(Language = "Italian")] IFoo ciao)
+ {
+ this.ciao = ciao;
+ }
+ }
+
+ public class AutowireTestConstructorNormal
+ {
+ public IFoo ciao;
+
+ [Autowired]
+ public AutowireTestConstructorNormal([Dialect(Language = "Italian")] IFoo ciao)
+ {
+ this.ciao = ciao;
+ }
+ }
+}
+
+namespace Spring.Objects.Factory.Attributes.ByValue
+{
+ public class AutowireTestFieldNormal
+ {
+ [Value("@(CiaoFoo)")]
+ public IFoo ciao;
+ }
+
+ public class AutowireTestPropertyNormal
+ {
+ [Value("@(CiaoFoo)")]
+ public IFoo Ciao { get; set; }
+ }
+
+ public class AutowireTestMethodNormal
+ {
+ public IFoo ciao;
+
+ [Autowired]
+ private void Prepare([Value("@(CiaoFoo)")] IFoo ciao)
+ {
+ this.ciao = ciao;
+ }
+ }
+
+ public class AutowireTestConstructorNormal
+ {
+ public IFoo ciao;
+
+ [Autowired]
+ public AutowireTestConstructorNormal([Value("@(CiaoFoo)")] IFoo ciao)
+ {
+ this.ciao = ciao;
+ }
+ }
+
+ public class AutowireTestPropertyPlaceHolder
+ {
+ [Value("${greeting}")]
+ public string greeting;
+ }
+
+}
+
+namespace Spring.Objects.Factory.Attributes.Collections
+{
+ public class AutowireTestList
+ {
+ [Autowired]
+ public IList foos;
+ }
+
+ public class AutowireTestSet
+ {
+ [Autowired]
+ public Spring.Collections.Generic.ISet foos;
+ }
+
+ public class AutowireTestDictionary
+ {
+ [Autowired]
+ public IDictionary foos;
+ }
+
+ public class AutowireTestDictionaryFail
+ {
+ [Autowired]
+ public IDictionary foos;
+ }
+
+ public class AutowireTestQualifier
+ {
+ [Autowired]
+ [Qualifier("ciao")]
+ public IList foos;
+ }
+
+
+}
\ No newline at end of file
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByQualifierAttributeObjects.xml b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByQualifierAttributeObjects.xml
new file mode 100644
index 00000000..74b98ba6
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByQualifierAttributeObjects.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByQualifierObjects.xml b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByQualifierObjects.xml
new file mode 100644
index 00000000..43de7378
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByQualifierObjects.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeFailObjects.xml b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeFailObjects.xml
new file mode 100644
index 00000000..db5c0fe1
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeFailObjects.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeNormalObjects.xml b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeNormalObjects.xml
new file mode 100644
index 00000000..dfa67481
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeNormalObjects.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeNotRequiredObjects.xml b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeNotRequiredObjects.xml
new file mode 100644
index 00000000..4dfff1e7
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypeNotRequiredObjects.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypePrimaryObjects.xml b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypePrimaryObjects.xml
new file mode 100644
index 00000000..d30bd950
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByTypePrimaryObjects.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByValueObjects.config b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByValueObjects.config
new file mode 100644
index 00000000..a8034dac
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByValueObjects.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByValueObjects.xml b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByValueObjects.xml
new file mode 100644
index 00000000..49e7d6e6
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/ByValueObjects.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/CollectionObjects.xml b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/CollectionObjects.xml
new file mode 100644
index 00000000..8623f311
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Attributes/CollectionObjects.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyPlaceholderConfigurerTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyPlaceholderConfigurerTests.cs
index a5ce40cd..02e5a183 100644
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyPlaceholderConfigurerTests.cs
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/PropertyPlaceholderConfigurerTests.cs
@@ -150,6 +150,7 @@ namespace Spring.Objects.Factory.Config
IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof(IConfigurableListableObjectFactory));
Expect.Call(mock.GetObjectDefinitionNames()).Return(new string [] {defName});
Expect.Call(mock.GetObjectDefinition(defName)).Return(def);
+ Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments();
mocks.ReplayAll();
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
@@ -422,6 +423,7 @@ namespace Spring.Objects.Factory.Config
IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof (IConfigurableListableObjectFactory));
Expect.Call(mock.GetObjectDefinitionNames()).Return(new string[] {"foo"});
Expect.Call(mock.GetObjectDefinition(null)).IgnoreArguments().Return(def);
+ Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments();
mocks.ReplayAll();
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
@@ -451,6 +453,7 @@ namespace Spring.Objects.Factory.Config
IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof (IConfigurableListableObjectFactory));
Expect.Call(mock.GetObjectDefinitionNames()).Return(new string[] {"foo"});
Expect.Call(mock.GetObjectDefinition(null)).IgnoreArguments().Return(def);
+ Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments();
mocks.ReplayAll();
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
@@ -548,6 +551,7 @@ namespace Spring.Objects.Factory.Config
IConfigurableListableObjectFactory mock = (IConfigurableListableObjectFactory) mocks.CreateMock(typeof(IConfigurableListableObjectFactory));
Expect.Call(mock.GetObjectDefinitionNames()).Return(new string [] {defName});
Expect.Call(mock.GetObjectDefinition(defName)).Return(def);
+ Expect.Call(delegate { mock.AddEmbeddedValueResolver(null); }).IgnoreArguments();
mocks.ReplayAll();
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/UnsupportedObjectDefinitionImplementation.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/UnsupportedObjectDefinitionImplementation.cs
index 41f6bb52..252cf996 100644
--- a/test/Spring/Spring.Core.Tests/Objects/Factory/UnsupportedObjectDefinitionImplementation.cs
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/UnsupportedObjectDefinitionImplementation.cs
@@ -73,6 +73,11 @@ namespace Spring.Objects.Factory
get { return false; }
}
+ public bool IsPrimary
+ {
+ get { return false; }
+ }
+
public string ParentName
{
get { return null; }
diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj
index ace68efb..913aabe2 100644
--- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj
+++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj
@@ -302,7 +302,19 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -316,6 +328,15 @@
+
+
+
+
+
+
+
+
+
@@ -864,6 +885,15 @@
+
+
+
+
+
+
+
+
+
Always
diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj
index 66411318..36ed0475 100644
--- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj
+++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj
@@ -318,11 +318,15 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -872,6 +876,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.build b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.build
index 2290ad36..05ddd1db 100644
--- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.build
+++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.build
@@ -40,6 +40,7 @@
+