SPRNET-1521 added AutowireAttributePostProcessor
This commit is contained in:
110
src/Spring/Spring.Core/Core/AttributeAccessorSupport.cs
Normal file
110
src/Spring/Spring.Core/Core/AttributeAccessorSupport.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class for <see cref="IAttributeAccessor"/>, providing
|
||||
/// a base implementation of all methods. To be extended by subclasses.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public abstract class AttributeAccessorSupport : IAttributeAccessor
|
||||
{
|
||||
/** Map with String keys and Object values */
|
||||
private readonly IDictionary<string, object> _attributes = new Dictionary<string, object>();
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/Spring/Spring.Core/Core/IAttributeAccessor.cs
Normal file
76
src/Spring/Spring.Core/Core/IAttributeAccessor.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
#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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface defining a generic contract for attaching and accessing metadata
|
||||
/// to/from arbitrary objects.
|
||||
/// </summary>
|
||||
public interface IAttributeAccessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Set the attribute defined by <code>name</code> to the supplied <code>value</code>.
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="name">the unique attribute key</param>
|
||||
/// <param name="value">the attribute value to be attached</param>
|
||||
void SetAttribute(string name, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of the attribute identified by <code>name</code>.
|
||||
/// Return <code>null</code> if the attribute doesn't exist.
|
||||
/// </summary>
|
||||
/// <param name="name">the unique attribute key</param>
|
||||
/// <returns>the current value of the attribute, if any</returns>
|
||||
object GetAttribute(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Remove the attribute identified by <code>name</code> and return its value.
|
||||
/// Return <code>null</code> if no attribute under <code>name</code> is found.
|
||||
/// </summary>
|
||||
/// <param name="name">the unique attribute key</param>
|
||||
/// <returns>The last value of the attribute, if any</returns>
|
||||
object RemoveAttribute(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Checks weather a specific attributes exists
|
||||
/// </summary>
|
||||
/// <param name="name">The unique attribute key</param>
|
||||
/// <returns>
|
||||
/// <code>true</code> if the attribute identified by <code>name</code> exists.
|
||||
/// Otherwise return <code>false</code>
|
||||
/// </returns>
|
||||
bool HasAttribute(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Return the names of all attributes.
|
||||
/// </summary>
|
||||
String[] AttributeNames { get; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ namespace Spring.Core
|
||||
private ConstructorInfo constructorInfo;
|
||||
|
||||
private readonly int parameterIndex;
|
||||
|
||||
private Type parameterType;
|
||||
|
||||
/// <summary>
|
||||
@@ -136,5 +137,34 @@ namespace Spring.Core
|
||||
{
|
||||
get { return constructorInfo; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the annotations associated with the specific method/constructor parameter.
|
||||
/// </summary>
|
||||
public Attribute[] ParameterAttributes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (methodInfo != null)
|
||||
return Attribute.GetCustomAttributes(methodInfo.GetParameters()[parameterIndex]);
|
||||
else
|
||||
return Attribute.GetCustomAttributes(constructorInfo.GetParameters()[parameterIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the annotations associated with the target method/constructor itself.
|
||||
/// </summary>
|
||||
public Attribute[] MethodAttributes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (methodInfo != null)
|
||||
return Attribute.GetCustomAttributes(methodInfo);
|
||||
else
|
||||
return Attribute.GetCustomAttributes(constructorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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 <em>cannot</em>
|
||||
/// 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).
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Constructor)]
|
||||
public class AutowiredAttribute : Attribute
|
||||
{
|
||||
private bool _required = true;
|
||||
|
||||
/// <summary>
|
||||
/// Defines it Autowired PostProcessor should fail if object is not set
|
||||
/// </summary>
|
||||
public bool Required
|
||||
{
|
||||
get { return _required; }
|
||||
set { _required = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,661 @@
|
||||
#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
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IInstantiationAwareObjectPostProcessor"/> implementation
|
||||
/// that autowires annotated fields, properties and arbitrary config methods.
|
||||
/// Such members to be injected are detected through an attribute: by default,
|
||||
/// Spring's <see cref="AutowiredAttribute"/>.
|
||||
///
|
||||
/// Only one constructor (at max) of any given bean class may carry this
|
||||
/// annotation with the 'required' parameter set to <code>true</code>,
|
||||
/// indicating <i>the</i> constructor to autowire when used as a Spring bean.
|
||||
/// If multiple <i>non-required</i> 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.
|
||||
/// <b>NOTE:</b> Annotation injection will be performed <i>before</i> XML injection;
|
||||
/// thus the latter configuration will override the former for properties wired through
|
||||
/// both approaches.
|
||||
/// </summary>
|
||||
public class AutowiredAttributeObjectPostProcessor : InstantiationAwareObjectPostProcessorAdapter,
|
||||
IObjectFactoryAware, IOrdered
|
||||
{
|
||||
private static readonly ILog Logger = LogManager.GetLogger<AutowiredAttributeObjectPostProcessor>();
|
||||
|
||||
private int _order = int.MaxValue - 2;
|
||||
|
||||
private static IConfigurableListableObjectFactory _objectFactory;
|
||||
|
||||
private SynchronizedHashtable _candidateConstructorsCache = new SynchronizedHashtable();
|
||||
|
||||
private readonly IDictionary<Type, InjectionMetadata> _injectionMetadataCache =
|
||||
new Dictionary<Type, InjectionMetadata>();
|
||||
|
||||
private IList<Type> _autowiredPropertyTypes = new List<Type>();
|
||||
|
||||
/// <summary>
|
||||
/// Return the order value of this object, where a higher value means greater in
|
||||
/// terms of sorting.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>Normally starting with 0 or 1, with <see cref="F:System.Int32.MaxValue"/> indicating
|
||||
/// greatest. Same order values will result in arbitrary positions for the affected
|
||||
/// objects.
|
||||
/// </p><p>Higher value can be interpreted as lower priority, consequently the first object
|
||||
/// has highest priority.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// The order value.
|
||||
/// </returns>
|
||||
public int Order
|
||||
{
|
||||
get { return _order; }
|
||||
private set { _order = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Callback that supplies the owning factory to an object instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Owning <see cref="T:Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// (may not be <see langword="null"/>). The object can immediately
|
||||
/// call methods on the factory.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <p>Invoked after population of normal object properties but before an init
|
||||
/// callback like <see cref="T:Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="M:Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// method or a custom init-method.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="T:Spring.Objects.ObjectsException">In case of initialization errors.
|
||||
/// </exception>
|
||||
public IObjectFactory ObjectFactory
|
||||
{
|
||||
set { _objectFactory = (IConfigurableListableObjectFactory) value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a Autowired Attribute Type
|
||||
/// </summary>
|
||||
public void AddAutowiredType(Type attributeType)
|
||||
{
|
||||
if (!_autowiredPropertyTypes.Contains(attributeType))
|
||||
_autowiredPropertyTypes.Add(attributeType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of an Autowire Post Processor
|
||||
/// with standard attributes of <see cref="AutowiredAttribute"/>
|
||||
/// and <see cref="ValueAttribute"/>
|
||||
/// </summary>
|
||||
public AutowiredAttributeObjectPostProcessor()
|
||||
{
|
||||
_autowiredPropertyTypes.Add(typeof(AutowiredAttribute));
|
||||
_autowiredPropertyTypes.Add(typeof(ValueAttribute));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the candidate constructors to use for the given object.
|
||||
/// </summary>
|
||||
/// <param name="objectType">The raw Type of the object.</param>
|
||||
/// <param name="objectName">Name of the object.</param>
|
||||
/// <returns>The candidate constructors, or <code>null</code> if none specified</returns>
|
||||
/// <exception cref="ObjectsException">in case of errors</exception>
|
||||
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<ConstructorInfo> candidates = new List<ConstructorInfo>(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);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds autowire candidates and verifies them
|
||||
/// </summary>
|
||||
/// <param name="objectType">
|
||||
/// The <see cref="System.Type"/> of the target object that is to be
|
||||
/// instantiated.
|
||||
/// </param>
|
||||
/// <param name="objectName">
|
||||
/// The name of the target object.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The object to expose instead of a default instance of the target
|
||||
/// object.
|
||||
/// </returns>
|
||||
/// <exception cref="Spring.Objects.ObjectsException">
|
||||
/// In the case of any errors.
|
||||
/// </exception>
|
||||
/// <seealso cref="Spring.Objects.Factory.Support.AbstractObjectDefinition.HasObjectType"/>
|
||||
/// <seealso cref="Spring.Objects.Factory.Support.IConfigurableObjectDefinition.FactoryMethodName"/>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Injects autoried annotated properties, fields, methods into objectInstance
|
||||
/// </summary>
|
||||
/// <param name="pvs"></param>
|
||||
/// <param name="pis"></param>
|
||||
/// <param name="objectInstance"></param>
|
||||
/// <param name="objectName">Name of the object.</param>
|
||||
/// <returns>The actual property values to apply to the given object (can be the
|
||||
/// passed-in PropertyValues instances0 or null to skip property population.</returns>
|
||||
public override IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, IList<PropertyInfo> 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<InjectionMetadata.InjectedElement>();
|
||||
|
||||
do
|
||||
{
|
||||
foreach (var autowiredType in _autowiredPropertyTypes)
|
||||
{
|
||||
var currElements = new List<InjectionMetadata.InjectedElement>();
|
||||
foreach (
|
||||
var property in
|
||||
objectType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public |
|
||||
BindingFlags.Instance))
|
||||
{
|
||||
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);
|
||||
}
|
||||
objectType = objectType.BaseType;
|
||||
} while (objectType != null && objectType != typeof (Object));
|
||||
|
||||
return new InjectionMetadata(objectType, elements);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register the specified bean as dependent on the autowired beans.
|
||||
/// </summary>
|
||||
private static void RegisterDependentObjects(string objectName, IList autowiredObjectNames)
|
||||
{
|
||||
if (objectName == null) return;
|
||||
|
||||
var objectDefinition = _objectFactory.GetObjectDefinition(objectName) as RootObjectDefinition;
|
||||
IList<string> dependsOn = new List<string>(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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class representing injection information about an annotated field.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class representing injection information about an annotated field.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal class for managing injection metadata.
|
||||
/// Not intended for direct use in applications.
|
||||
/// </summary>
|
||||
public class InjectionMetadata
|
||||
{
|
||||
private static readonly ILog Logger = LogManager.GetLogger<InjectionMetadata>();
|
||||
|
||||
private readonly IList<InjectedElement> _injectedElements;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="targetType"></param>
|
||||
/// <param name="elements"></param>
|
||||
public InjectionMetadata(Type targetType, IList<InjectedElement> elements)
|
||||
{
|
||||
_injectedElements = new List<InjectedElement>();
|
||||
if (elements.Count > 0)
|
||||
{
|
||||
foreach (var element in elements)
|
||||
{
|
||||
Logger.Debug(m => m("Found injected element on class [" + targetType.Name + "]: " + element));
|
||||
_injectedElements.Add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="objectDefinition"></param>
|
||||
public void CheckConfigMembers(RootObjectDefinition objectDefinition)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Inject values for members into object instance
|
||||
/// </summary>
|
||||
/// <param name="instance"></param>
|
||||
/// <param name="objectName"></param>
|
||||
/// <param name="pvs"></param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an element that needs to be injected
|
||||
/// </summary>
|
||||
public abstract class InjectedElement
|
||||
{
|
||||
/// <summary>
|
||||
/// The Property, field, method or constructor info
|
||||
/// </summary>
|
||||
protected readonly MemberInfo _member;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new inject element
|
||||
/// </summary>
|
||||
/// <param name="member"></param>
|
||||
protected InjectedElement(MemberInfo member)
|
||||
{
|
||||
_member = member;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ececuted to inject value to associated memeber info
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="requestingObjectName"></param>
|
||||
/// <param name="pvs"></param>
|
||||
public abstract void Inject(object target, string requestingObjectName, IPropertyValues pvs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
#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 Spring.Collections.Generic;
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IAutowireCandidateResolver"/> implementation that matches bean definition qualifier
|
||||
/// against <see cref="QualifierAttribute"/> on the field or parameter to be autowired.
|
||||
/// Also supports suggested expression values through a <see cref="ValueAttribute"/> attribute.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class QualifierAnnotationAutowireCandidateResolver : IAutowireCandidateResolver, IObjectFactoryAware
|
||||
{
|
||||
private IObjectFactory _objectFactory;
|
||||
|
||||
private Collections.Generic.ISet<Type> _qualifierTypes = new HashedSet<Type>();
|
||||
|
||||
private Type _valueAttributeType = typeof(ValueAttribute);
|
||||
|
||||
public IObjectFactory ObjectFactory
|
||||
{
|
||||
set { _objectFactory = value; }
|
||||
}
|
||||
|
||||
public Type ValueAttributeType
|
||||
{
|
||||
set { _valueAttributeType = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new QualifierAnnotationAutowireCandidateResolver
|
||||
/// for Spring's standard <see cref="QualifierAttribute"/> attribute.
|
||||
/// </summary>
|
||||
public QualifierAnnotationAutowireCandidateResolver()
|
||||
{
|
||||
_qualifierTypes.Add(typeof(QualifierAttribute));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new QualifierAnnotationAutowireCandidateResolver
|
||||
/// for the given qualifier attribute type.
|
||||
/// </summary>
|
||||
/// <param name="qualifierType">the qualifier attribute to look for</param>
|
||||
public QualifierAnnotationAutowireCandidateResolver(Type qualifierType)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(qualifierType, "'qualifierType' must not be null");
|
||||
_qualifierTypes.Add(qualifierType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new QualifierAnnotationAutowireCandidateResolver
|
||||
/// for the given qualifier attribute types.
|
||||
/// </summary>
|
||||
/// <param name="qualifierTypes">the qualifier annotations to look for</param>
|
||||
public QualifierAnnotationAutowireCandidateResolver(Collections.Generic.ISet<Type> qualifierTypes) {
|
||||
AssertUtils.ArgumentNotNull(qualifierTypes, "'qualifierTypes' must not be null");
|
||||
foreach(var type in qualifierTypes)
|
||||
{
|
||||
if (!_qualifierTypes.Contains(type))
|
||||
_qualifierTypes.Add(type);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register the given type to be used as a qualifier when autowiring.
|
||||
/// <p>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.</p>
|
||||
/// <p>This implementation only supports annotations as qualifier types.
|
||||
/// The default is Spring's <see cref="QualifierAttribute"/> attribute which serves
|
||||
/// as a qualifier for direct use and also as a meta attribute.</p>
|
||||
/// </summary>
|
||||
/// <param name="qualifierType">the attribute type to register</param>
|
||||
public void AddQualifierType(Type qualifierType) {
|
||||
_qualifierTypes.Add(qualifierType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether the provided object definition is an autowire candidate.
|
||||
/// <p>To be considered a candidate the object's <em>autowire-candidate</em>
|
||||
/// 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 <em>qualifier</em>, 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.</p>
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Match the given qualifier annotations against the candidate bean definition.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the given attribute type is a recognized qualifier type.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Match the given qualifier attribute against the candidate bean definition.
|
||||
/// </summary>
|
||||
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<string, object> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether the given dependency carries a value attribute.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine a suggested value from any of the given candidate annotations.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Spring.Objects.Factory.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
|
||||
public class QualifierAttribute : Attribute
|
||||
{
|
||||
private readonly string _value;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate a new qualifier with an empty name
|
||||
/// </summary>
|
||||
public QualifierAttribute()
|
||||
{
|
||||
_value = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate a new qualifier with a givin name
|
||||
/// </summary>
|
||||
/// <param name="value">name to use as qualifier</param>
|
||||
public QualifierAttribute(string value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name associated with this qualifier
|
||||
/// </summary>
|
||||
public string Value { get { return _value; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks weather the attribute is the same
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; } }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
/// </summary>
|
||||
/// <param name="methodParameter">The MethodParameter to wrap.</param>
|
||||
/// <param name="required">if set to <c>true</c> if the dependency is required.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new descriptor for a property.
|
||||
/// Considers the dependency as 'eager'.
|
||||
/// <param name="property">property to wrap</param>
|
||||
/// <param name="required">required whether the dependency is required</param>
|
||||
/// </summary>
|
||||
public DependencyDescriptor(PropertyInfo property, bool required)
|
||||
: this(property, required, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new descriptor for a property.
|
||||
/// <param name="property">property to wrap</param>
|
||||
/// <param name="required ">whether the dependency is required</param>
|
||||
/// <param name="eager">whether this dependency is 'eager' in the sense of</param>
|
||||
/// eagerly resolving potential target beans for type matching
|
||||
/// </summary>
|
||||
public DependencyDescriptor(PropertyInfo property, bool required, bool eager)
|
||||
{
|
||||
this.property = property;
|
||||
this.required = required;
|
||||
this.eager = eager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new descriptor for a field.
|
||||
/// Considers the dependency as 'eager'.
|
||||
/// <param name="field">field to wrap</param>
|
||||
/// <param name="required">whether the dependency is required</param>
|
||||
/// </summary>
|
||||
public DependencyDescriptor(FieldInfo field, bool required)
|
||||
: this(field, required, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new descriptor for a field.
|
||||
/// <param name="field">field to wrap</param>
|
||||
/// <param name="required ">whether the dependency is required</param>
|
||||
/// <param name="eager">whether this dependency is 'eager' in the sense of</param>
|
||||
/// eagerly resolving potential target beans for type matching
|
||||
/// </summary>
|
||||
public DependencyDescriptor(FieldInfo field, bool required, bool eager)
|
||||
{
|
||||
this.field = field;
|
||||
this.required = required;
|
||||
this.eager = eager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this dependency is required.
|
||||
@@ -79,7 +135,17 @@ namespace Spring.Objects.Factory.Config
|
||||
/// <value>The type of the dependency (never <code>null</code></value>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,5 +167,41 @@ namespace Spring.Objects.Factory.Config
|
||||
{
|
||||
get { return methodParameter; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Attributes assigned to Field, Property or Paramater
|
||||
/// </summary>
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the member info
|
||||
/// </summary>
|
||||
public string DependencyName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (methodParameter != null)
|
||||
return methodParameter.ParameterName();
|
||||
if (property != null)
|
||||
return property.Name;
|
||||
if (field != null)
|
||||
return field.Name;
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -163,5 +164,17 @@ namespace Spring.Objects.Factory.Config
|
||||
/// </param>
|
||||
void RegisterCustomConverter(Type requiredType, TypeConverter converter);
|
||||
|
||||
/// <summary>
|
||||
/// Add a String resolver for embedded values such as annotation attributes.
|
||||
/// </summary>
|
||||
/// <param name="valueResolver">the String resolver to apply to embedded values</param>
|
||||
void AddEmbeddedValueResolver(IStringValueResolver valueResolver);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve the given embedded value, e.g. an annotation attribute.
|
||||
/// </summary>
|
||||
/// <param name="value">the value to resolve</param>
|
||||
/// <returns>the resolved value (may be the original value as-is)</returns>
|
||||
string ResolveEmbeddedValue(string value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,5 +226,12 @@ namespace Spring.Objects.Factory.Config
|
||||
/// <c>true</c> if this instance is autowire candidate; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
bool IsAutowireCandidate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
bool IsPrimary { get; }
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,17 @@ namespace Spring.Objects.Factory.Config
|
||||
get { return aliases; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks wether a givin candidate name has a defined object or alias
|
||||
/// </summary>
|
||||
/// <param name="candidateName">name to check if exists</param>
|
||||
/// <returns></returns>
|
||||
public bool MatchesName(string candidateName)
|
||||
{
|
||||
return (!string.IsNullOrEmpty(candidateName) &&
|
||||
(candidateName.Equals(ObjectName) || Aliases.Contains(candidateName)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 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;
|
||||
|
||||
@@ -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
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Rick Evans (.NET)</author>
|
||||
[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<string>(other.DependsOn);
|
||||
FactoryMethodName = other.FactoryMethodName;
|
||||
FactoryObjectName = other.FactoryObjectName;
|
||||
@@ -541,6 +545,67 @@ namespace Spring.Objects.Factory.Support
|
||||
set { autowireCandidate = value;}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public bool IsPrimary
|
||||
{
|
||||
get { return primary; }
|
||||
set { primary = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a qualifier to be used for autowire candidate resolution,
|
||||
/// keyed by the qualifier's type name.
|
||||
/// <see cref="AutowireCandidateQualifier"/>
|
||||
/// </summary>
|
||||
public void AddQualifier(AutowireCandidateQualifier qualifier)
|
||||
{
|
||||
qualifiers.Add(qualifier.TypeName, qualifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return whether this bean has the specified qualifier.
|
||||
/// </summary>
|
||||
public bool HasQualifier(string typeName)
|
||||
{
|
||||
return qualifiers.ContainsKey(typeName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the qualifier mapped to the provided type name.
|
||||
/// </summary>
|
||||
public AutowireCandidateQualifier GetQualifier(string typeName)
|
||||
{
|
||||
return qualifiers.ContainsKey(typeName) ? qualifiers[typeName] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return all registered qualifiers.
|
||||
/// </summary>
|
||||
/// <returns>the Set of <see cref="AutowireCandidateQualifier"/> objects.</returns>
|
||||
public Set<AutowireCandidateQualifier> GetQualifiers()
|
||||
{
|
||||
return new OrderedSet<AutowireCandidateQualifier>(qualifiers.Values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the qualifiers from the supplied AbstractBeanDefinition to this bean definition.
|
||||
/// </summary>
|
||||
/// <param name="source">the AbstractBeanDefinition to copy from</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the initializer method.
|
||||
/// </summary>
|
||||
@@ -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<string> dependsOn;
|
||||
private bool autowireCandidate = true;
|
||||
|
||||
private bool primary;
|
||||
|
||||
private readonly IDictionary<string, AutowireCandidateQualifier> qualifiers =
|
||||
new Dictionary<string, AutowireCandidateQualifier>();
|
||||
|
||||
private string initMethodName = null;
|
||||
private string destroyMethodName = null;
|
||||
private string factoryMethodName = null;
|
||||
|
||||
@@ -1603,6 +1603,11 @@ namespace Spring.Objects.Factory.Support
|
||||
/// </summary>
|
||||
private ISet objectPostProcessors = new SortedSet(new ObjectOrderComparator());
|
||||
|
||||
/// <summary>
|
||||
/// String Resolver applied to Autowired value injections
|
||||
/// </summary>
|
||||
private ISet embeddedValueResolvers = new SortedSet();
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether any IInstantiationAwareBeanPostProcessors have been registered
|
||||
/// </summary>
|
||||
@@ -2385,6 +2390,30 @@ namespace Spring.Objects.Factory.Support
|
||||
return this.singletonsInCreation.Contains(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a String resolver for embedded values such as annotation attributes.
|
||||
/// </summary>
|
||||
/// <param name="valueResolver">the String resolver to apply to embedded values</param>
|
||||
public void AddEmbeddedValueResolver(IStringValueResolver valueResolver)
|
||||
{
|
||||
embeddedValueResolvers.Add(valueResolver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolve the given embedded value, e.g. an annotation attribute.
|
||||
/// </summary>
|
||||
/// <param name="value">the value to resolve</param>
|
||||
/// <returns>the resolved value (may be the original value as-is)</returns>
|
||||
public string ResolveEmbeddedValue(string value)
|
||||
{
|
||||
string result = value;
|
||||
foreach(IStringValueResolver resolver in embeddedValueResolvers)
|
||||
{
|
||||
result = resolver.ParseAndResolveVariables(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>
|
||||
/// that will get applied to objects created by this factory.
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public class AutowireCandidateQualifier : ObjectMetadataAttributeAccessor
|
||||
{
|
||||
public static string VALUE_KEY = "Value";
|
||||
|
||||
private readonly string _typeName;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct a qualifier to match against an annotation of the
|
||||
/// given type.
|
||||
/// </summary>
|
||||
/// <param name="type">type the annotation type</param>
|
||||
public AutowireCandidateQualifier(Type type) : this(type.Name)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a qualifier to match against an annotation of the
|
||||
/// given type name.
|
||||
/// <p>The type name may match the fully-qualified class name of
|
||||
/// the annotation or the short class name (without the package).</p>
|
||||
/// </summary>
|
||||
/// <param name="typeName">the name of the annotation type</param>
|
||||
public AutowireCandidateQualifier(string typeName)
|
||||
{
|
||||
Trace.Assert(typeName != null, "Type name must not be null");
|
||||
_typeName = typeName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a qualifier to match against an annotation of the
|
||||
/// given type whose <code>value</code> attribute also matches
|
||||
/// the specified value.
|
||||
/// </summary>
|
||||
/// <param name="type">the annotation type</param>
|
||||
/// <param name="value">the annotation value to match</param>
|
||||
public AutowireCandidateQualifier(Type type, object value) : this(type.Name, value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a qualifier to match against an annotation of the
|
||||
/// given type name whose <code>value</code> attribute also matches
|
||||
/// the specified value.
|
||||
/// <p>The type name may match the fully-qualified class name of
|
||||
/// the annotation or the short class name (without the package).</p>
|
||||
/// </summary>
|
||||
/// <param name="typeName">the name of the annotation type</param>
|
||||
/// <param name="value">the annotation value to match</param>
|
||||
public AutowireCandidateQualifier(string typeName, object value)
|
||||
{
|
||||
Trace.Assert(typeName != null, "Type name must not be null");
|
||||
_typeName = typeName;
|
||||
SetAttribute(VALUE_KEY, value);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public String TypeName
|
||||
{
|
||||
get { return _typeName; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
/// <returns>A SimpleAutowireCandidateResolver</returns>
|
||||
public static IAutowireCandidateResolver CreateAutowireCandidateResolver()
|
||||
{
|
||||
return new SimpleAutowireCandidateResolver();
|
||||
return new QualifierAnnotationAutowireCandidateResolver();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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
|
||||
/// <summary>
|
||||
/// IDictionary from dependency type to corresponding autowired value
|
||||
/// </summary>
|
||||
private readonly IDictionary resolvableDependencies = new Hashtable();
|
||||
private readonly IDictionary<Type, object> resolvableDependencies = new Dictionary<Type, object>();
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -1112,6 +1115,19 @@ namespace Spring.Objects.Factory.Support
|
||||
IList autowiredObjectNames)
|
||||
{
|
||||
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();
|
||||
@@ -1133,6 +1149,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.
|
||||
@@ -1155,9 +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)
|
||||
@@ -1168,7 +1224,75 @@ namespace Spring.Objects.Factory.Support
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the primary autowire candidate in the given set of beans.
|
||||
/// </summary>
|
||||
/// <param name="candidateObjects">a Map of candidate names and candidate instances
|
||||
/// that match the required type</param>
|
||||
/// <param name="descriptor">the target dependency to match against</param>
|
||||
/// <returns>the name of the primary candidate, or <code>null</code> if none found</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return whether the object definition for the given object name has been
|
||||
/// marked as a primary object.
|
||||
/// </summary>
|
||||
/// <param name="objectName">the name of the bean</param>
|
||||
/// <param name="objectInstance">the corresponding bean instance</param>
|
||||
/// <returns>whether the given bean qualifies as primary</returns>
|
||||
private bool IsPrimary(string objectName, object objectInstance) {
|
||||
if (ContainsObjectDefinition(objectName)) {
|
||||
return GetMergedObjectDefinition(objectName, true).IsPrimary;
|
||||
}
|
||||
return (ParentObjectFactory is DefaultListableObjectFactory &&
|
||||
((DefaultListableObjectFactory)ParentObjectFactory).IsPrimary(objectName, objectInstance));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether the given candidate name matches the bean name or the aliases
|
||||
///stored in this bean definition.
|
||||
/// </summary>
|
||||
protected bool MatchesObjectName(string objectName, string candidateName)
|
||||
{
|
||||
return (candidateName != null &&
|
||||
(candidateName.Equals(objectName) || GetAliases(objectName).Contains(candidateName)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the no such object definition exception for an unresolvable dependency
|
||||
@@ -1188,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];
|
||||
@@ -1201,6 +1325,7 @@ namespace Spring.Objects.Factory.Support
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < candidateNames.Count; i++)
|
||||
{
|
||||
string candidateName = candidateNames[i];
|
||||
|
||||
@@ -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
|
||||
/// <c>true</c> if the object definition qualifies as autowire candidate; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
bool IsAutowireCandidate(ObjectDefinitionHolder odHolder, DependencyDescriptor descriptor);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether a default value is suggested for the given dependency.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">The descriptor for the target method parameter or field</param>
|
||||
/// <returns>The value suggested (typically an expression String),
|
||||
/// or <c>null</c> if none found
|
||||
/// </returns>
|
||||
Object GetSuggestedValue(DependencyDescriptor descriptor);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -45,5 +45,18 @@ namespace Spring.Objects.Factory.Support
|
||||
{
|
||||
return odHolder.ObjectDefinition.IsAutowireCandidate;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether a default value is suggested for the given dependency.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">The descriptor for the target method parameter or field</param>
|
||||
/// <returns>The value suggested (typically an expression String),
|
||||
/// or <c>null</c> if none found
|
||||
/// </returns>
|
||||
public object GetSuggestedValue(DependencyDescriptor descriptor)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,6 +298,11 @@ namespace Spring.Objects.Factory.Xml
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public const string PropertyElement = "property";
|
||||
|
||||
/// <summary>
|
||||
/// A qualifier definition used for fine grained autowiring
|
||||
/// </summary>
|
||||
public const string QualifierElement = "qualifier";
|
||||
|
||||
/// <summary>
|
||||
/// A reference to another managed object or static
|
||||
@@ -581,6 +586,16 @@ namespace Spring.Objects.Factory.Xml
|
||||
/// </summary>
|
||||
public const string AutowireAttribute = "autowire";
|
||||
|
||||
/// <summary>
|
||||
/// Attribute element to farther deifne the qualifier of an object
|
||||
/// </summary>
|
||||
public const string AttributeElement = "attribute";
|
||||
|
||||
/// <summary>
|
||||
/// The primary object for autwired injection
|
||||
/// </summary>
|
||||
public const string PrimaryAttribute = "primary";
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut alternative to specifying a key element in a
|
||||
/// dictionary entry element with <c><ref object="..."/></c>.
|
||||
@@ -598,6 +613,11 @@ namespace Spring.Objects.Factory.Xml
|
||||
/// </summary>
|
||||
public const string MergeAttribute = "merge";
|
||||
|
||||
/// <summary>
|
||||
/// Defined meta attributes to be used for Autowire objects
|
||||
/// </summary>
|
||||
public const string MetaElement = "meta";
|
||||
|
||||
/// <summary>
|
||||
/// The string of characters that delimit object names.
|
||||
/// </summary>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the meta upplied meta attributes if the given object element
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse qualifier sub-elements of the given bean element.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a qualifier element.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse property value subelements of the given object element.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,595 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsd:schema xmlns="http://www.springframework.net" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:vs="http://schemas.microsoft.com/Visual-Studio-Intellisense" targetNamespace="http://www.springframework.net" elementFormDefault="qualified" attributeFormDefault="unqualified" vs:friendlyname="Spring.NET Configuration" vs:ishtmlschema="false" vs:iscasesensitive="true" vs:requireattributequotes="true" vs:defaultnamespacequalifier="" vs:defaultnsprefix="">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Spring Objects XML Schema Definition
|
||||
Based on Spring Beans DTD, authored by Rod Johnson & Juergen Hoeller
|
||||
|
||||
Author: Griffin Caprio
|
||||
|
||||
This defines a simple and consistent way of creating a namespace
|
||||
of managed objects configured by a Spring XmlObjectFactory.
|
||||
This document type is used by most Spring functionality, including
|
||||
web application contexts, which are based on object factories.
|
||||
|
||||
Each object element in this document defines an object.
|
||||
Typically the object type (System.Type is specified, along with plain vanilla
|
||||
object properties.
|
||||
|
||||
Object instances can be "singletons" (shared instances) or "prototypes"
|
||||
(independent instances).
|
||||
|
||||
References among objects are supported, i.e. setting an object property
|
||||
to refer to another object in the same factory or an ancestor factory.
|
||||
|
||||
As alternative to object references, "inner object definitions" can be used.
|
||||
Singleton flags and names of such "inner object" are always ignored:
|
||||
Inner object are anonymous prototypes.
|
||||
|
||||
There is also support for lists, dictionaries, and sets.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<!-- base types -->
|
||||
<xsd:complexType name="identifiedType" abstract="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[The unique identifier for a bean. The scope of the identifier is the enclosing object factory.]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="id" type="xsd:ID">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[The unique identifier for an object.]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:simpleType name="nonNullString">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>Defines a base type for any required string. Defines a string with a minimum length of 0</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="0"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="description">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Element containing informative text describing the purpose of the enclosing
|
||||
element. Always optional.
|
||||
Used primarily for user documentation of XML object definition documents.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:restriction base="nonNullString"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="valueObject">
|
||||
<xsd:simpleContent>
|
||||
<xsd:extension base="xsd:string">
|
||||
<xsd:attribute name="type" type="nonNullString" use="optional"/>
|
||||
</xsd:extension>
|
||||
</xsd:simpleContent>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="expression">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="2"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="value" type="nonNullString" use="required"/>
|
||||
</xsd:complexType>
|
||||
<!--
|
||||
Defines a reference to another object in this factory or an external
|
||||
factory (parent or included factory).
|
||||
-->
|
||||
<xsd:complexType name="objectReference">
|
||||
<xsd:attribute name="object" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="local" type="xsd:IDREF" use="optional"/>
|
||||
<xsd:attribute name="parent" type="nonNullString" use="optional"/>
|
||||
<!--
|
||||
References must specify a name of the target object.
|
||||
The "object" attribute can reference any name from any object in the context,
|
||||
to be checked at runtime.
|
||||
Local references, using the "local" attribute, have to use object ids;
|
||||
they can be checked by this DTD, thus should be preferred for references
|
||||
within the same object factory XML file.
|
||||
-->
|
||||
</xsd:complexType>
|
||||
<!-- Defines a reference to another object or a type. -->
|
||||
<xsd:complexType name="objectOrClassReference">
|
||||
<xsd:attribute name="object" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="local" type="xsd:IDREF" use="optional"/>
|
||||
<xsd:attribute name="type" type="nonNullString" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:group name="objectList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="description" type="description" minOccurs="0"/>
|
||||
<xsd:choice>
|
||||
<xsd:element name="object" type="vanillaObject"/>
|
||||
<!--
|
||||
Defines a reference to another object in this factory or an external
|
||||
factory (parent or included factory).
|
||||
-->
|
||||
<xsd:element name="ref" type="objectReference"/>
|
||||
<!--
|
||||
Defines a string property value, which must also be the id of another
|
||||
object in this factory or an external factory (parent or included factory).
|
||||
While a regular 'value' element could instead be used for the same effect,
|
||||
using idref in this case allows validation of local object ids by the xml
|
||||
parser, and name completion by helper tools.
|
||||
-->
|
||||
<xsd:element name="idref" type="objectReference"/>
|
||||
<!--
|
||||
A objectList can contain multiple inner object, ref, collection, or value elements.
|
||||
Lists are untyped, pending generics support, although references will be
|
||||
strongly typed.
|
||||
A objectList can also map to an array type. The necessary conversion
|
||||
is automatically performed by AbstractObjectFactory.
|
||||
-->
|
||||
<xsd:element name="list">
|
||||
<xsd:complexType>
|
||||
<xsd:group ref="objectList" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:attribute name="element-type" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="merge" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<!--
|
||||
A set can contain multiple inner object, ref, collection, or value elements.
|
||||
Sets are untyped, pending generics support, although references will be
|
||||
strongly typed.
|
||||
-->
|
||||
<xsd:element name="set">
|
||||
<xsd:complexType>
|
||||
<xsd:group ref="objectList" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:attribute name="element-type" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="merge" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<!--
|
||||
A Spring map is a mapping from a string key to object (a .NET IDictionary).
|
||||
Maps may be empty.
|
||||
-->
|
||||
<xsd:element name="dictionary" type="objectMap"/>
|
||||
<!--
|
||||
Name-values elements differ from map elements in that values must be strings.
|
||||
Name-values may be empty.
|
||||
-->
|
||||
<xsd:element name="name-values" type="objectNameValues"/>
|
||||
<!--
|
||||
Contains a string representation of a property value.
|
||||
The property may be a string, or may be converted to the
|
||||
required type using the System.ComponentModel.TypeConverter
|
||||
machinery. This makes it possible for application developers
|
||||
to write custom TypeConverter implementations that can
|
||||
convert strings to objects.
|
||||
|
||||
Note that this is recommended for simple objects only.
|
||||
Configure more complex objects by setting properties to references
|
||||
to other objects.
|
||||
-->
|
||||
<xsd:element name="value" type="valueObject"/>
|
||||
<!--
|
||||
Contains a string representation of an expression.
|
||||
-->
|
||||
<xsd:element name="expression" type="expression"/>
|
||||
<!--
|
||||
Denotes a .NET null value. Necessary because an empty "value" tag
|
||||
will resolve to an empty String, which will not be resolved to a
|
||||
null value unless a special TypeConverter does so.
|
||||
-->
|
||||
<xsd:element name="null" />
|
||||
<xsd:any namespace="##other" processContents="strict" />
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:group>
|
||||
<xsd:complexType name="objectNameValues">
|
||||
<xsd:sequence>
|
||||
<!--
|
||||
The "value" attribute is the string value of the property. The "key"
|
||||
attribute is the name of the property.
|
||||
-->
|
||||
<xsd:element name="add" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType mixed="true">
|
||||
<xsd:attribute name="key" type="nonNullString" use="required"/>
|
||||
<xsd:attribute name="value" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="delimiters" use="optional" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="merge" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="importElement">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>Import an external file containing object definitions into this file.</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="resource" type="nonNullString" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="aliasElement">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>Defines an additional alias name for an object definition.</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="name" type="nonNullString" use="required"/>
|
||||
<xsd:attribute name="alias" type="nonNullString" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="objectMap">
|
||||
<xsd:sequence>
|
||||
<xsd:element type="mapEntryElement" name="entry" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="key-type" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="value-type" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="merge" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="mapEntryElement">
|
||||
<xsd:sequence>
|
||||
<xsd:element type="mapKeyElement" name="key" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:group ref="objectList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="key" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="value" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="expression" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="key-ref" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="value-ref" type="nonNullString" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="mapKeyElement">
|
||||
<xsd:group ref="objectList" minOccurs="1"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="lookupMethod">
|
||||
<xsd:attribute name="name" type="nonNullString" use="required"/>
|
||||
<xsd:attribute name="object" type="nonNullString" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="constructorArgument">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>Defines constructor argument.</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:group ref="objectList" minOccurs="0"/>
|
||||
<!--
|
||||
The constructor-arg tag can have an optional named parameter attribute,
|
||||
to specify a named parameter in the constructor argument list.
|
||||
-->
|
||||
<xsd:attribute name="name" type="nonNullString" use="optional"/>
|
||||
<!--
|
||||
The constructor-arg tag can have an optional index attribute,
|
||||
to specify the exact index in the constructor argument list. Only needed
|
||||
to avoid ambiguities, e.g. in case of 2 arguments of the same type.
|
||||
-->
|
||||
<xsd:attribute name="index" type="nonNullString" use="optional"/>
|
||||
<!--
|
||||
The constructor-arg tag can have an optional type attribute,
|
||||
to specify the exact type of the constructor argument. Only needed
|
||||
to avoid ambiguities, e.g. in case of 2 single argument constructors
|
||||
that can both be converted from a String.
|
||||
-->
|
||||
<xsd:attribute name="type" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="value" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="expression" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="ref" type="nonNullString" use="optional"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="property">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>Defines property.</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:group ref="objectList" minOccurs="0"/>
|
||||
<!-- The property name attribute is the name of the objects property. -->
|
||||
<xsd:attribute name="name" type="nonNullString" use="required"/>
|
||||
<xsd:attribute name="value" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="expression" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="ref" type="nonNullString" use="optional"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="metaType">
|
||||
<xsd:attribute name="key" type="nonNullString" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The key name of the metadata attribute being defined.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="value" type="nonNullString" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The value of the metadata attribute being defined (as a simple String).
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="qualifierType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Object definitions can provide qualifiers to match against attributes
|
||||
on a field or parameter for fine-grained autowire candidate resolution.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="attribute" type="metaType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="type" type="nonNullString" default="Spring.Objects.Factory.Attributes.QualifierAttribute"/>
|
||||
<xsd:attribute name="value" type="nonNullString" use="optional"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="vanillaObject">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>Defines a single named object.</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="description" type="description" minOccurs="0" maxOccurs="1"/>
|
||||
<!--
|
||||
Object definitions can specify zero or more constructor arguments.
|
||||
They correspond to either a specific index of the constructor argument list
|
||||
or are supposed to be matched generically by type.
|
||||
This is an alternative to "autowire constructor".
|
||||
-->
|
||||
<xsd:element name="constructor-arg" type="constructorArgument" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<!--
|
||||
Object definitions can have zero or more properties.
|
||||
Spring supports primitives, references to other objects in the same or
|
||||
related factories, lists, dictionaries and properties.
|
||||
-->
|
||||
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<!--
|
||||
Object definitions can specify zero or more lookup-methods.
|
||||
-->
|
||||
<xsd:element name="lookup-method" type="lookupMethod" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<!-- Object definitions can have zero or more replaced-methods. -->
|
||||
<xsd:element name="replaced-method" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="arg-type" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="match" type="nonNullString" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="nonNullString" use="required"/>
|
||||
<xsd:attribute name="replacer" type="nonNullString" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<!-- Object definitions can have zero or more subscriptions. -->
|
||||
<xsd:element name="listener" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="ref" type="objectOrClassReference" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<!-- The event(s) the object is interested in. -->
|
||||
<xsd:attribute name="event" type="nonNullString" use="optional"/>
|
||||
<!-- The name or name pattern of the method that will handle the event(s). -->
|
||||
<xsd:attribute name="method" type="nonNullString" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<!-- Object definition can have zero or more meta attribute definitions used for autowiring dependencies -->
|
||||
<xsd:element name="meta" type="metaType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<!-- Object definition can have zero or more qualifier definition used for autowiring dependencies -->
|
||||
<xsd:element name="qualifier" type="qualifierType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<!--
|
||||
Objects can be identified by an id, to enable reference checking.
|
||||
There are constraints on a valid XML id: if you want to reference your object
|
||||
in .NET code using a name that's illegal as an XML id, use the optional
|
||||
"name" attribute. If neither given, the object type name is used as id.
|
||||
-->
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional"/>
|
||||
<!--
|
||||
Optional. Can be used to create one or more aliases illegal in an id.
|
||||
Multiple aliases can be separated by any number of spaces or commas.
|
||||
-->
|
||||
<xsd:attribute name="name" type="nonNullString" use="optional"/>
|
||||
<!--
|
||||
Each object definition must specify the full, assembly qualified of the type,
|
||||
or the name of the parent object from which the type can be worked out.
|
||||
|
||||
Note that a child object definition that references a parent will just
|
||||
add respectively override property values and be able to change the
|
||||
singleton status. It will inherit all of the parent's other parameters
|
||||
like lazy initialization or autowire settings.
|
||||
-->
|
||||
<xsd:attribute name="type" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="parent" type="nonNullString" use="optional"/>
|
||||
<!--
|
||||
Is this object "abstract", i.e. not meant to be instantiated itself but
|
||||
rather just serving as parent for concrete child object definitions?
|
||||
Default is false. Specify true to tell the object factory to not try to
|
||||
instantiate that particular object in any case.
|
||||
-->
|
||||
<xsd:attribute name="abstract" type="xsd:boolean" use="optional" default="false"/>
|
||||
<!--
|
||||
Is this object a "singleton" (one shared instance, which will
|
||||
be returned by all calls to GetObject() with the id),
|
||||
or a "prototype" (independent instance resulting from each call to
|
||||
getObject(). Default is singleton.
|
||||
|
||||
Singletons are most commonly used, and are ideal for multi-threaded
|
||||
service objects.
|
||||
-->
|
||||
<xsd:attribute name="singleton" type="xsd:boolean" use="optional" default="true"/>
|
||||
<!--
|
||||
Optional attribute controlling the scope of singleton instances. It is
|
||||
only applicable to ASP.Net web applications and it has no effect on prototype
|
||||
objects. Applications other than ASP.Net web applications simply ignore this attribute.
|
||||
It has 3 possible values:
|
||||
1. "application"
|
||||
Default object scope. Objects defined with application scope will behave like
|
||||
traditional singleton objects. Same instance will be returned from every call
|
||||
to IApplicationContext.GetObject()
|
||||
|
||||
2. "session"
|
||||
Objects with this scope will be stored within user's HTTP session. Session scope
|
||||
is typically used for objects such as shopping cart, user profile, etc.
|
||||
|
||||
3. "request"
|
||||
Object with this scope will be initialized for each HTTP request, but unlike with prototype
|
||||
objects, same instance will be returned from all calls to IApplicationContext.GetObject()
|
||||
within the same HTTP request. For example, if one ASP page forwards request to another using
|
||||
Server.Transfer method, they can easily share the state by configuring dependency to the same
|
||||
request-scoped object.
|
||||
-->
|
||||
<xsd:attribute name="scope" use="optional" default="application">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="application"/>
|
||||
<xsd:enumeration value="session"/>
|
||||
<xsd:enumeration value="request"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<!--
|
||||
Is this object to be lazily initialized?
|
||||
If false, it will get instantiated on startup by object factories
|
||||
that perform eager initialization of singletons.
|
||||
-->
|
||||
<xsd:attribute name="lazy-init" use="optional" default="default">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="true"/>
|
||||
<xsd:enumeration value="false"/>
|
||||
<xsd:enumeration value="default"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<!--
|
||||
Optional attribute controlling whether to "autowire" object properties.
|
||||
This is an automagical process in which object references don't need to be coded
|
||||
explicitly in the XML object definition file, but Spring works out dependencies.
|
||||
|
||||
There are 5 modes:
|
||||
|
||||
1. "no"
|
||||
The traditional Spring default. No automagical wiring. Object references
|
||||
must be defined in the XML file via the <ref> element. We recommend this
|
||||
in most cases as it makes documentation more explicit.
|
||||
|
||||
2. "byName"
|
||||
Autowiring by property name. If a object of class Cat exposes a dog property,
|
||||
Spring will try to set this to the value of the object "dog" in the current factory.
|
||||
|
||||
3. "byType"
|
||||
Autowiring if there is exactly one object of the property type in the object factory.
|
||||
If there is more than one, a fatal error is raised, and you can't use byType
|
||||
autowiring for that object. If there is none, nothing special happens - use
|
||||
dependency-check="objects" to raise an error in that case.
|
||||
|
||||
4. "constructor"
|
||||
Analogous to "byType" for constructor arguments. If there isn't exactly one object
|
||||
of the constructor argument type in the object factory, a fatal error is raised.
|
||||
|
||||
5. "autodetect"
|
||||
Chooses "constructor" or "byType" through introspection of the object class.
|
||||
If a default constructor is found, "byType" gets applied.
|
||||
|
||||
The latter two are similar to PicoContainer and make object factories simple to
|
||||
configure for small namespaces, but doesn't work as well as standard Spring
|
||||
behaviour for bigger applications.
|
||||
|
||||
Note that explicit dependencies, i.e. "property" and "constructor-arg" elements,
|
||||
always override autowiring. Autowire behaviour can be combined with dependency
|
||||
checking, which will be performed after all autowiring has been completed.
|
||||
-->
|
||||
<xsd:attribute name="autowire" use="optional" default="default">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="no"/>
|
||||
<xsd:enumeration value="byName"/>
|
||||
<xsd:enumeration value="byType"/>
|
||||
<xsd:enumeration value="constructor"/>
|
||||
<xsd:enumeration value="autodetect"/>
|
||||
<xsd:enumeration value="default"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<!--
|
||||
Is this object the rpimary object if type resolving during Autowiring
|
||||
-->
|
||||
<xsd:attribute name="primary" type="xsd:boolean" use="optional" default="false"/>
|
||||
<!--
|
||||
Optional attribute controlling whether to check whether all this
|
||||
objects dependencies, expressed in its properties, are satisfied.
|
||||
Default is no dependency checking.
|
||||
|
||||
"simple" type dependency checking includes primitives and String
|
||||
"object" includes collaborators (other objects in the factory)
|
||||
"all" includes both types of dependency checking
|
||||
-->
|
||||
<xsd:attribute name="dependency-check" use="optional" default="default">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="none"/>
|
||||
<xsd:enumeration value="objects"/>
|
||||
<xsd:enumeration value="simple"/>
|
||||
<xsd:enumeration value="all"/>
|
||||
<xsd:enumeration value="default"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<!--
|
||||
The names of the objects that this object depends on being initialized.
|
||||
The object factory will guarantee that these objects get initialized before.
|
||||
|
||||
Note that dependencies are normally expressed through object properties or
|
||||
constructor arguments. This property should just be necessary for other kinds
|
||||
of dependencies like statics (*ugh*) or database preparation on startup.
|
||||
-->
|
||||
<xsd:attribute name="depends-on" type="nonNullString" use="optional"/>
|
||||
<!--
|
||||
Optional attribute for the name of the custom initialization method
|
||||
to invoke after setting object properties. The method must have no arguments,
|
||||
but may throw any exception.
|
||||
-->
|
||||
<xsd:attribute name="init-method" type="nonNullString" use="optional"/>
|
||||
<!--
|
||||
Optional attribute for the name of the custom destroy method to invoke
|
||||
on object factory shutdown. The method must have no arguments,
|
||||
but may throw any exception. Note: Only invoked on singleton objects!
|
||||
-->
|
||||
<xsd:attribute name="destroy-method" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="factory-method" type="nonNullString" use="optional"/>
|
||||
<xsd:attribute name="factory-object" type="nonNullString" use="optional"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="objects">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>The document root. At least one object definition is required.</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="description" type="description" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="import" type="importElement"/>
|
||||
<xsd:element name="alias" type="aliasElement"/>
|
||||
<xsd:element name="object" type="vanillaObject"/>
|
||||
<xsd:any namespace="##other" processContents="strict"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
<!--
|
||||
Default values for all object definitions. Can be overridden at
|
||||
the "object" level. See those attribute definitions for details.
|
||||
-->
|
||||
<xsd:attribute name="default-lazy-init" type="xsd:boolean" use="optional" default="false"/>
|
||||
<xsd:attribute name="default-merge" type="xsd:boolean" use="optional" default="false"/>
|
||||
<xsd:attribute name="default-dependency-check" use="optional" default="none">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="none"/>
|
||||
<xsd:enumeration value="objects"/>
|
||||
<xsd:enumeration value="simple"/>
|
||||
<xsd:enumeration value="all"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="default-autowire" use="optional" default="no">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="no"/>
|
||||
<xsd:enumeration value="byName"/>
|
||||
<xsd:enumeration value="byType"/>
|
||||
<xsd:enumeration value="constructor"/>
|
||||
<xsd:enumeration value="autodetect"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--This file is auto-generated by the XML Schema Designer. It holds layout information for components on the designer surface.-->
|
||||
<XSDDesignerLayout Style="LeftRight" layoutVersion="2" viewPortLeft="0" viewPortTop="0" zoom="100">
|
||||
<identifiedType_XmlComplexType left="1317" top="167061" width="5292" height="3757" selected="0" zOrder="8" index="0" expanded="1" />
|
||||
<nonNullString_XmlSimpleType left="1317" top="1254" width="5292" height="3625" selected="0" zOrder="5" index="1" expanded="1" />
|
||||
<description_XmlSimpleType left="1317" top="5387" width="5292" height="3625" selected="0" zOrder="6" index="2" expanded="1" />
|
||||
<valueObject_XmlComplexType left="1317" top="9520" width="5292" height="3625" selected="0" zOrder="7" index="3" expanded="1" />
|
||||
<expression_XmlComplexType left="1317" top="13653" width="5292" height="3625" selected="0" zOrder="9" index="4" expanded="1">
|
||||
<property_XmlElement left="7243" top="13653" width="5292" height="3625" selected="0" zOrder="10" index="0" expanded="0" />
|
||||
</expression_XmlComplexType>
|
||||
<objectReference_XmlComplexType left="1317" top="17786" width="5292" height="3757" selected="0" zOrder="12" index="5" expanded="1" />
|
||||
<objectOrClassReference_XmlComplexType left="1317" top="22051" width="5292" height="3757" selected="0" zOrder="13" index="6" expanded="1" />
|
||||
<objectList_XmlGroup left="1317" top="43376" width="5292" height="3757" selected="0" zOrder="14" index="7" expanded="1">
|
||||
<_x0028_group1_x0029__XmlChoice left="7243" top="43376" width="5292" height="3757" selected="0" zOrder="15" index="1" expanded="1">
|
||||
<object_XmlElement left="13169" top="26316" width="5292" height="3757" selected="0" zOrder="17" index="0" expanded="0" />
|
||||
<ref_XmlElement left="13169" top="30581" width="5292" height="3757" selected="0" zOrder="19" index="1" expanded="0" />
|
||||
<idref_XmlElement left="13169" top="34846" width="5292" height="3757" selected="0" zOrder="21" index="2" expanded="0" />
|
||||
<list_XmlElement left="13169" top="39111" width="5292" height="3757" selected="0" zOrder="23" index="3" expanded="1">
|
||||
<_x0028_group1_x0029__XmlChoice left="19095" top="39111" width="5292" height="3757" selected="0" zOrder="25" index="1" expanded="0" />
|
||||
</list_XmlElement>
|
||||
<set_XmlElement left="13169" top="43376" width="5292" height="3757" selected="0" zOrder="27" index="4" expanded="1">
|
||||
<_x0028_group1_x0029__XmlChoice left="19095" top="43376" width="5292" height="3757" selected="0" zOrder="29" index="1" expanded="0" />
|
||||
</set_XmlElement>
|
||||
<dictionary_XmlElement left="13169" top="47641" width="5292" height="3757" selected="0" zOrder="31" index="5" expanded="0" />
|
||||
<name-values_XmlElement left="13169" top="51906" width="5292" height="3757" selected="0" zOrder="33" index="6" expanded="0" />
|
||||
<value_XmlElement left="13169" top="56171" width="5292" height="3757" selected="0" zOrder="35" index="7" expanded="0" />
|
||||
<expression_XmlElement left="13169" top="60436" width="5292" height="3757" selected="0" zOrder="37" index="8" expanded="0" />
|
||||
</_x0028_group1_x0029__XmlChoice>
|
||||
</objectList_XmlGroup>
|
||||
<objectNameValues_XmlComplexType left="1317" top="64701" width="5292" height="3757" selected="0" zOrder="39" index="8" expanded="1">
|
||||
<add_XmlElement left="7243" top="64701" width="5292" height="3757" selected="0" zOrder="40" index="0" expanded="1" />
|
||||
</objectNameValues_XmlComplexType>
|
||||
<importElement_XmlComplexType left="1317" top="68966" width="5292" height="3757" selected="0" zOrder="42" index="9" expanded="1" />
|
||||
<aliasElement_XmlComplexType left="1317" top="73231" width="5292" height="3757" selected="0" zOrder="43" index="10" expanded="1" />
|
||||
<objectMap_XmlComplexType left="1317" top="77496" width="5292" height="3757" selected="0" zOrder="44" index="11" expanded="1">
|
||||
<entry_XmlElement left="7243" top="77496" width="5292" height="3757" selected="0" zOrder="45" index="0" expanded="0" />
|
||||
</objectMap_XmlComplexType>
|
||||
<mapEntryElement_XmlComplexType left="1317" top="83893" width="5292" height="3757" selected="0" zOrder="47" index="12" expanded="1">
|
||||
<key_XmlElement left="7243" top="81761" width="5292" height="3757" selected="0" zOrder="48" index="0" expanded="0" />
|
||||
<ref_x003D_objectList_XmlGroup left="7243" top="86026" width="5292" height="3757" selected="0" zOrder="50" index="1" expanded="0" />
|
||||
</mapEntryElement_XmlComplexType>
|
||||
<mapKeyElement_XmlComplexType left="1317" top="90291" width="5292" height="3757" selected="0" zOrder="52" index="13" expanded="1">
|
||||
<_x0028_group1_x0029__XmlChoice left="7243" top="90291" width="5292" height="3757" selected="0" zOrder="53" index="1" expanded="0" />
|
||||
</mapKeyElement_XmlComplexType>
|
||||
<lookupMethod_XmlComplexType left="1317" top="94556" width="5292" height="3757" selected="0" zOrder="55" index="14" expanded="1" />
|
||||
<constructorArgument_XmlComplexType left="1317" top="98821" width="5292" height="3757" selected="0" zOrder="56" index="15" expanded="1">
|
||||
<_x0028_group1_x0029__XmlChoice left="7243" top="98821" width="5292" height="3757" selected="0" zOrder="57" index="1" expanded="0" />
|
||||
</constructorArgument_XmlComplexType>
|
||||
<property_XmlComplexType left="1317" top="103086" width="5292" height="3757" selected="0" zOrder="59" index="16" expanded="1">
|
||||
<_x0028_group1_x0029__XmlChoice left="7243" top="103086" width="5292" height="3757" selected="0" zOrder="60" index="1" expanded="0" />
|
||||
</property_XmlComplexType>
|
||||
<vanillaObject_XmlComplexType left="1317" top="123716" width="5292" height="3757" selected="0" zOrder="62" index="17" expanded="1">
|
||||
<constructor-arg_XmlElement left="7243" top="107351" width="5292" height="3757" selected="0" zOrder="63" index="1" expanded="0" />
|
||||
<property_XmlElement left="7243" top="111616" width="5292" height="3757" selected="0" zOrder="65" index="2" expanded="0" />
|
||||
<lookup-method_XmlElement left="7243" top="115881" width="5292" height="3757" selected="0" zOrder="67" index="3" expanded="0" />
|
||||
<replaced-method_XmlElement left="7243" top="120146" width="5292" height="3757" selected="0" zOrder="69" index="4" expanded="1">
|
||||
<arg-type_XmlElement left="13169" top="120146" width="5292" height="3757" selected="0" zOrder="71" index="0" expanded="1" />
|
||||
</replaced-method_XmlElement>
|
||||
<listener_XmlElement left="7243" top="124411" width="5292" height="3757" selected="0" zOrder="73" index="5" expanded="1">
|
||||
<ref_XmlElement left="13169" top="124411" width="5292" height="3757" selected="0" zOrder="75" index="0" expanded="0" />
|
||||
</listener_XmlElement>
|
||||
<scope_XmlAttribute left="7243" top="130065" width="5292" height="979" selected="0" zOrder="77" index="12" expanded="1">
|
||||
<_x0028_scope_x0029__XmlSimpleType left="13169" top="128676" width="5292" height="3757" selected="0" zOrder="79" index="0" expanded="1" />
|
||||
</scope_XmlAttribute>
|
||||
<lazy-init_XmlAttribute left="7243" top="134330" width="5292" height="979" selected="0" zOrder="81" index="13" expanded="1">
|
||||
<_x0028_lazy-init_x0029__XmlSimpleType left="13169" top="132941" width="5292" height="3757" selected="0" zOrder="83" index="0" expanded="1" />
|
||||
</lazy-init_XmlAttribute>
|
||||
<autowire_XmlAttribute left="7243" top="138595" width="5292" height="979" selected="0" zOrder="85" index="14" expanded="1">
|
||||
<_x0028_autowire_x0029__XmlSimpleType left="13169" top="137206" width="5292" height="3757" selected="0" zOrder="87" index="0" expanded="1" />
|
||||
</autowire_XmlAttribute>
|
||||
<dependency-check_XmlAttribute left="7243" top="142860" width="5292" height="979" selected="0" zOrder="89" index="15" expanded="1">
|
||||
<_x0028_dependency-check_x0029__XmlSimpleType left="13169" top="141471" width="5292" height="3757" selected="0" zOrder="91" index="0" expanded="1" />
|
||||
</dependency-check_XmlAttribute>
|
||||
</vanillaObject_XmlComplexType>
|
||||
<objects_XmlElement left="1317" top="155704" width="5292" height="3757" selected="0" zOrder="93" index="18" expanded="1">
|
||||
<_x0028_group1_x0029__XmlChoice left="7243" top="150001" width="5292" height="3757" selected="0" zOrder="94" index="1" expanded="1">
|
||||
<import_XmlElement left="13169" top="145736" width="5292" height="3757" selected="0" zOrder="96" index="0" expanded="0" />
|
||||
<alias_XmlElement left="13169" top="150001" width="5292" height="3757" selected="0" zOrder="98" index="1" expanded="0" />
|
||||
<object_XmlElement left="13169" top="154266" width="5292" height="3757" selected="0" zOrder="100" index="2" expanded="0" />
|
||||
</_x0028_group1_x0029__XmlChoice>
|
||||
<default-dependency-check_XmlAttribute left="7243" top="159920" width="5292" height="979" selected="0" zOrder="102" index="3" expanded="1">
|
||||
<_x0028_default-dependency-check_x0029__XmlSimpleType left="13169" top="158531" width="5292" height="3757" selected="0" zOrder="104" index="0" expanded="1" />
|
||||
</default-dependency-check_XmlAttribute>
|
||||
<default-autowire_XmlAttribute left="7243" top="164185" width="5292" height="979" selected="0" zOrder="106" index="4" expanded="1">
|
||||
<_x0028_default-autowire_x0029__XmlSimpleType left="13169" top="162796" width="5292" height="3757" selected="0" zOrder="108" index="0" expanded="1" />
|
||||
</default-autowire_XmlAttribute>
|
||||
</objects_XmlElement>
|
||||
</XSDDesignerLayout>
|
||||
37
src/Spring/Spring.Core/Objects/IObjectMetadataElement.cs
Normal file
37
src/Spring/Spring.Core/Objects/IObjectMetadataElement.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to be implemented by bean metadata elements
|
||||
/// that carry a configuration source object.
|
||||
/// </summary>
|
||||
public interface IObjectMetadataElement
|
||||
{
|
||||
/// <summary>
|
||||
/// Return the configuration source <code>Object</code> for this metadata element
|
||||
/// (may be <code>null</code>).
|
||||
/// </summary>
|
||||
Object Source { get; }
|
||||
}
|
||||
}
|
||||
95
src/Spring/Spring.Core/Objects/ObjectMetadataAttribute.cs
Normal file
95
src/Spring/Spring.Core/Objects/ObjectMetadataAttribute.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public class ObjectMetadataAttribute : IObjectMetadataElement
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
private readonly object _value;
|
||||
|
||||
private object _source;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new AttributeValue instance.
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the attribute (never <code>null</code>)</param>
|
||||
/// <param name="value">the value of the attribute (possibly before type conversion)</param>
|
||||
public ObjectMetadataAttribute(string name, object value)
|
||||
{
|
||||
Trace.Assert(name != null, "Name must not be null");
|
||||
_name = name;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return the name of the attribute.
|
||||
/// </summary>
|
||||
public string Name { get { return _name; } }
|
||||
|
||||
/// <summary>
|
||||
/// Return the value of the attribute.
|
||||
/// </summary>
|
||||
public object Value { get { return _value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Set the configuration source <code>Object</code> for this metadata element.
|
||||
/// <p>The exact type of the object will depend on the configuration mechanism used.</p>
|
||||
/// </summary>
|
||||
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 + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#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 Spring.Core;
|
||||
|
||||
namespace Spring.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension of <see cref="AttributeAccessorSupport"/>,
|
||||
/// holding attributes as <see cref="IObjectMetadataElement"/> objects in order
|
||||
/// to keep track of the definition source.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ObjectMetadataAttributeAccessor : AttributeAccessorSupport, IObjectMetadataElement
|
||||
{
|
||||
private object _source;
|
||||
|
||||
/// <summary>
|
||||
/// Set the configuration source <code>object</code> for this metadata element.
|
||||
/// <p>The exact type of the object will depend on the configuration mechanism used.</p>
|
||||
/// </summary>
|
||||
public object Source
|
||||
{
|
||||
get { return _source; }
|
||||
set { _source = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add the given BeanMetadataAttribute to this accessor's set of attributes.
|
||||
/// </summary>
|
||||
/// <param name="attribute">The BeanMetadataAttribute object to register</param>
|
||||
public void AddMetadataAttribute(ObjectMetadataAttribute attribute)
|
||||
{
|
||||
base.SetAttribute(attribute.Name, attribute);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Look up the given BeanMetadataAttribute in this accessor's set of attributes.
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the attribute</param>
|
||||
/// <returns>the corresponding BeanMetadataAttribute object,
|
||||
/// or <code>null</code> if no such attribute defined
|
||||
/// </returns>
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -278,12 +278,14 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Context\Support\XmlApplicationContextArgs.cs" />
|
||||
<Compile Include="Core\AttributeAccessorSupport.cs" />
|
||||
<Compile Include="Core\CannotLoadObjectTypeException.cs" />
|
||||
<Compile Include="Core\ComposedCriteria.cs" />
|
||||
<Compile Include="Core\ControlFlowFactory.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Core\Conventions.cs" />
|
||||
<Compile Include="Core\IAttributeAccessor.cs" />
|
||||
<Compile Include="Core\IO\EncodedResource.cs" />
|
||||
<Compile Include="Core\IPriorityOrdered.cs" />
|
||||
<Compile Include="Core\MethodArgumentsCriteria.cs" />
|
||||
@@ -676,8 +678,14 @@
|
||||
<Compile Include="Objects\Factory\Attributes\InitDestroyAttributeObjectPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\PostConstructAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\PreDestroyAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowiredAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowiredAttributeObjectPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\InjectionMetadata.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\QualifierAnnotationAutowireCandidateResolver.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\QualifierAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\RequiredAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\RequiredAttributeObjectPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\ValueAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Config\AbstractConfigurer.cs" />
|
||||
<Compile Include="Objects\Factory\Config\CommandLineArgsVariableSource.cs" />
|
||||
<Compile Include="Objects\Factory\Config\ConfigSectionVariableSource.cs" />
|
||||
@@ -711,9 +719,13 @@
|
||||
<Compile Include="Objects\Factory\Parsing\ObjectDefinitionParsingException.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\Problem.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\ReaderContext.cs" />
|
||||
<Compile Include="Objects\Factory\Support\AutowireCandidateQualifier.cs" />
|
||||
<Compile Include="Objects\Factory\Support\DelegateInvokingFactoryObject.cs" />
|
||||
<Compile Include="Objects\Factory\Support\IObjectDefinitionRegistryPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Support\ObjectScope.cs" />
|
||||
<Compile Include="Objects\IObjectMetadataElement.cs" />
|
||||
<Compile Include="Objects\ObjectMetadataAttribute.cs" />
|
||||
<Compile Include="Objects\ObjectMetadataAttributeAccessor.cs" />
|
||||
<Compile Include="Util\ConstructorInstantiationInfo.cs" />
|
||||
<Compile Include="Objects\Factory\Support\GenericObjectDefinition.cs" />
|
||||
<Compile Include="Objects\Factory\Support\IAutowireCandidateResolver.cs" />
|
||||
@@ -1144,6 +1156,7 @@
|
||||
<Compile Include="Util\IErrorHandler.cs" />
|
||||
<Compile Include="Util\IEventExceptionsCollector.cs" />
|
||||
<Compile Include="Util\IoUtils.cs" />
|
||||
<Compile Include="Util\IStringValueResolver.cs" />
|
||||
<Compile Include="Util\ITextPosition.cs" />
|
||||
<Compile Include="Util\ObjectUtils.cs" />
|
||||
<Compile Include="Util\ReflectionException.cs" />
|
||||
@@ -1232,6 +1245,7 @@
|
||||
</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Objects\Factory\Xml\spring-objects-1.3.xsd" />
|
||||
<EmbeddedResource Include="Objects\Factory\Xml\spring-objects-2.0.xsd" />
|
||||
<None Include="Spring.Core.build" />
|
||||
<EmbeddedResource Include="Validation\Config\spring-validation-1.3.xsd" />
|
||||
<EmbeddedResource Include="Validation\Config\spring-validation-1.1.xsd" />
|
||||
|
||||
@@ -280,12 +280,14 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Context\Support\XmlApplicationContextArgs.cs" />
|
||||
<Compile Include="Core\AttributeAccessorSupport.cs" />
|
||||
<Compile Include="Core\CannotLoadObjectTypeException.cs" />
|
||||
<Compile Include="Core\ComposedCriteria.cs" />
|
||||
<Compile Include="Core\ControlFlowFactory.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Core\Conventions.cs" />
|
||||
<Compile Include="Core\IAttributeAccessor.cs" />
|
||||
<Compile Include="Core\IO\EncodedResource.cs" />
|
||||
<Compile Include="Core\IPriorityOrdered.cs" />
|
||||
<Compile Include="Core\MethodArgumentsCriteria.cs" />
|
||||
@@ -678,8 +680,14 @@
|
||||
<Compile Include="Objects\Factory\Attributes\InitDestroyAttributeObjectPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\PostConstructAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\PreDestroyAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowiredAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowiredAttributeObjectPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\InjectionMetadata.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\QualifierAnnotationAutowireCandidateResolver.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\QualifierAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\RequiredAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\RequiredAttributeObjectPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\ValueAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Config\AbstractConfigurer.cs" />
|
||||
<Compile Include="Objects\Factory\Config\CommandLineArgsVariableSource.cs" />
|
||||
<Compile Include="Objects\Factory\Config\ConfigSectionVariableSource.cs" />
|
||||
@@ -713,9 +721,13 @@
|
||||
<Compile Include="Objects\Factory\Parsing\ObjectDefinitionParsingException.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\Problem.cs" />
|
||||
<Compile Include="Objects\Factory\Parsing\ReaderContext.cs" />
|
||||
<Compile Include="Objects\Factory\Support\AutowireCandidateQualifier.cs" />
|
||||
<Compile Include="Objects\Factory\Support\DelegateInvokingFactoryObject.cs" />
|
||||
<Compile Include="Objects\Factory\Support\IObjectDefinitionRegistryPostProcessor.cs" />
|
||||
<Compile Include="Objects\Factory\Support\ObjectScope.cs" />
|
||||
<Compile Include="Objects\IObjectMetadataElement.cs" />
|
||||
<Compile Include="Objects\ObjectMetadataAttribute.cs" />
|
||||
<Compile Include="Objects\ObjectMetadataAttributeAccessor.cs" />
|
||||
<Compile Include="Stereotype\ControllerAttribute.cs" />
|
||||
<Compile Include="Util\ConstructorInstantiationInfo.cs" />
|
||||
<Compile Include="Objects\Factory\Support\GenericObjectDefinition.cs" />
|
||||
@@ -1146,6 +1158,7 @@
|
||||
<Compile Include="Util\IErrorHandler.cs" />
|
||||
<Compile Include="Util\IEventExceptionsCollector.cs" />
|
||||
<Compile Include="Util\IoUtils.cs" />
|
||||
<Compile Include="Util\IStringValueResolver.cs" />
|
||||
<Compile Include="Util\ITextPosition.cs" />
|
||||
<Compile Include="Util\ObjectUtils.cs" />
|
||||
<Compile Include="Util\ReflectionException.cs" />
|
||||
@@ -1235,6 +1248,9 @@
|
||||
</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Objects\Factory\Xml\spring-objects-1.3.xsd" />
|
||||
<EmbeddedResource Include="Objects\Factory\Xml\spring-objects-2.0.xsd">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<None Include="Spring.Core.build" />
|
||||
<EmbeddedResource Include="Validation\Config\spring-validation-1.3.xsd" />
|
||||
<EmbeddedResource Include="Validation\Config\spring-validation-1.1.xsd" />
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<resources basedir="." prefix="Spring.Objects.Factory.Xml">
|
||||
<include name="Objects/Factory/Xml/spring-objects-1.1.xsd" />
|
||||
<include name="Objects/Factory/Xml/spring-objects-1.3.xsd" />
|
||||
<include name="Objects/Factory/Xml/spring-objects-2.0.xsd" />
|
||||
</resources>
|
||||
<resources basedir="." prefix="Spring.Objects.Factory.Xml">
|
||||
<include name="Objects/Factory/Xml/spring-tool-1.1.xsd" />
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all attribute properties with values for a specific attribute type
|
||||
/// </summary>
|
||||
/// <param name="attribute">attribute to check against</param>
|
||||
/// <returns>collection of all properties with values</returns>
|
||||
public static IDictionary<string, object> GetAttributeProperties(Attribute attribute)
|
||||
{
|
||||
Type attributeType = attribute.GetType();
|
||||
IDictionary<string, object> attributes = new Dictionary<string, object>();
|
||||
foreach(var property in attributeType.GetProperties())
|
||||
{
|
||||
object value = property.GetValue(attribute, null);
|
||||
attributes.Add(property.Name, value);
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default name value of an attribute and a specific property
|
||||
/// </summary>
|
||||
/// <param name="attribute">attribute from where to get the default value</param>
|
||||
/// <param name="propertyName">property to get the default value</param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/Spring/Spring.Core/Util/IStringValueResolver.cs
Normal file
20
src/Spring/Spring.Core/Util/IStringValueResolver.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Spring.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple strategy interface for resolving a String value.
|
||||
/// </summary>
|
||||
public interface IStringValueResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolve the given String value, for example parsing placeholders.
|
||||
/// </summary>
|
||||
/// <param name="value">the original String value</param>
|
||||
/// <returns>the resolved String value</returns>
|
||||
string ParseAndResolveVariables(string value);
|
||||
}
|
||||
}
|
||||
@@ -412,6 +412,19 @@ namespace Spring.Util
|
||||
return (o1 == o2 || (o1 != null && o1.Equals(o2)));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return as hash code for the given object; typically the value of
|
||||
/// <code>{@link Object#hashCode()}</code>. If the object is an array,
|
||||
/// this method will delegate to any of the <code>nullSafeHashCode</code>
|
||||
/// methods for arrays in this class. If the object is <code>null</code>,
|
||||
/// this method returns 0.
|
||||
/// </summary>
|
||||
public static int NullSafeHashCode(object o1)
|
||||
{
|
||||
return (o1 != null ? o1.GetHashCode() : 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the first element in the supplied <paramref name="enumerator"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<IFoo> foos;
|
||||
}
|
||||
|
||||
public class AutowireTestSet
|
||||
{
|
||||
[Autowired]
|
||||
public Spring.Collections.Generic.ISet<IFoo> foos;
|
||||
}
|
||||
|
||||
public class AutowireTestDictionary
|
||||
{
|
||||
[Autowired]
|
||||
public IDictionary<string, IFoo> foos;
|
||||
}
|
||||
|
||||
public class AutowireTestDictionaryFail
|
||||
{
|
||||
[Autowired]
|
||||
public IDictionary<IFoo, IFoo> foos;
|
||||
}
|
||||
|
||||
public class AutowireTestQualifier
|
||||
{
|
||||
[Autowired]
|
||||
[Qualifier("ciao")]
|
||||
public IList<IFoo> foos;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object type="Spring.Objects.Factory.Attributes.AutowiredAttributeObjectPostProcessor, Spring.Core" />
|
||||
|
||||
<object id="HelloFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.HelloFoo, Spring.Core.Tests">
|
||||
<qualifier type="Spring.Objects.Factory.Attributes.ByQualifierAttribute.DialectAttribute">
|
||||
<attribute key="Language" value="English" />
|
||||
</qualifier>
|
||||
</object>
|
||||
|
||||
<object id="CiaoFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.CiaoFoo, Spring.Core.Tests">
|
||||
<qualifier type="Spring.Objects.Factory.Attributes.ByQualifierAttribute.DialectAttribute">
|
||||
<attribute key="Language" value="Italian" />
|
||||
</qualifier>
|
||||
</object>
|
||||
|
||||
<object id="AutowireTestField"
|
||||
type="Spring.Objects.Factory.Attributes.ByQualifierAttribute.AutowireTestFieldNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestProperty"
|
||||
type="Spring.Objects.Factory.Attributes.ByQualifierAttribute.AutowireTestPropertyNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestMethod"
|
||||
type="Spring.Objects.Factory.Attributes.ByQualifierAttribute.AutowireTestMethodNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestConstructor"
|
||||
type="Spring.Objects.Factory.Attributes.ByQualifierAttribute.AutowireTestConstructorNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
</objects>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object type="Spring.Objects.Factory.Attributes.AutowiredAttributeObjectPostProcessor, Spring.Core" />
|
||||
|
||||
<object id="HelloFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.HelloFoo, Spring.Core.Tests">
|
||||
<qualifier value="hello" />
|
||||
</object>
|
||||
|
||||
<object id="CiaoFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.CiaoFoo, Spring.Core.Tests">
|
||||
<qualifier value="ciao" />
|
||||
</object>
|
||||
|
||||
<object id="AutowireTestField"
|
||||
type="Spring.Objects.Factory.Attributes.ByQualifier.AutowireTestFieldNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestProperty"
|
||||
type="Spring.Objects.Factory.Attributes.ByQualifier.AutowireTestPropertyNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestMethod"
|
||||
type="Spring.Objects.Factory.Attributes.ByQualifier.AutowireTestMethodNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestConstructor"
|
||||
type="Spring.Objects.Factory.Attributes.ByQualifier.AutowireTestConstructorNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
</objects>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object type="Spring.Objects.Factory.Attributes.AutowiredAttributeObjectPostProcessor, Spring.Core" />
|
||||
|
||||
<object id="HelloFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.HelloFoo, Spring.Core.Tests" />
|
||||
|
||||
<object id="CiaoFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.CiaoFoo, Spring.Core.Tests" />
|
||||
|
||||
<object id="AutowireTestFieldNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestFieldNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestPropertyNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestPropertyNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestMethodNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestMethodNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestConstructorNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestConstructorNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
</objects>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object type="Spring.Objects.Factory.Attributes.AutowiredAttributeObjectPostProcessor, Spring.Core" />
|
||||
|
||||
<object id="HelloFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.HelloFoo, Spring.Core.Tests" />
|
||||
|
||||
<object id="AutowireTestFieldNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestFieldNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestPropertyNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestPropertyNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestMethodNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestMethodNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestConstructorNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestConstructorNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
</objects>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object type="Spring.Objects.Factory.Attributes.AutowiredAttributeObjectPostProcessor, Spring.Core" />
|
||||
|
||||
<object id="AutowireTestField"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestFieldNotRequired, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestProperty"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestPropertyNotRequired, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestMethod"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestMethodNotRequired, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
</objects>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object type="Spring.Objects.Factory.Attributes.AutowiredAttributeObjectPostProcessor, Spring.Core" />
|
||||
|
||||
<object id="HelloFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.HelloFoo, Spring.Core.Tests"
|
||||
primary="true"/>
|
||||
|
||||
<object id="CiaoFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.CiaoFoo, Spring.Core.Tests" />
|
||||
|
||||
<object id="AutowireTestFieldNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestFieldNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestPropertyNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestPropertyNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestMethodNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestMethodNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestConstructorNormal"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.AutowireTestConstructorNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
</objects>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
|
||||
<configSections>
|
||||
<sectionGroup name="spring">
|
||||
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
|
||||
</sectionGroup>
|
||||
<section name="NameValues" type="System.Configuration.NameValueSectionHandler"/>
|
||||
</configSections>
|
||||
|
||||
<NameValues>
|
||||
<add key="greeting" value="ciao"/>
|
||||
</NameValues>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object id="appPropertyConfigurer" type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
|
||||
<property name="Location" value="assembly://Spring.Core.Tests/Spring.Objects.Factory.Attributes/ByValueObjects.config" />
|
||||
<property name="ConfigSections" value="NameValues" />
|
||||
</object>
|
||||
|
||||
<object type="Spring.Objects.Factory.Attributes.AutowiredAttributeObjectPostProcessor, Spring.Core" />
|
||||
|
||||
<object id="HelloFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.HelloFoo, Spring.Core.Tests" />
|
||||
|
||||
<object id="CiaoFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.CiaoFoo, Spring.Core.Tests" />
|
||||
|
||||
<object id="AutowireTestField"
|
||||
type="Spring.Objects.Factory.Attributes.ByValue.AutowireTestFieldNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestProperty"
|
||||
type="Spring.Objects.Factory.Attributes.ByValue.AutowireTestPropertyNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestMethod"
|
||||
type="Spring.Objects.Factory.Attributes.ByValue.AutowireTestMethodNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestConstructor"
|
||||
type="Spring.Objects.Factory.Attributes.ByValue.AutowireTestConstructorNormal, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestPropertyPlaceHolder"
|
||||
type="Spring.Objects.Factory.Attributes.ByValue.AutowireTestPropertyPlaceHolder, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
</objects>
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object type="Spring.Objects.Factory.Attributes.AutowiredAttributeObjectPostProcessor, Spring.Core" />
|
||||
|
||||
<object id="HelloFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.HelloFoo, Spring.Core.Tests">
|
||||
<qualifier value="hello" />
|
||||
</object>
|
||||
|
||||
<object id="CiaoFoo"
|
||||
type="Spring.Objects.Factory.Attributes.ByType.CiaoFoo, Spring.Core.Tests">
|
||||
<qualifier value="ciao" />
|
||||
</object>
|
||||
|
||||
<object id="AutowireTestList"
|
||||
type="Spring.Objects.Factory.Attributes.Collections.AutowireTestList, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestSet"
|
||||
type="Spring.Objects.Factory.Attributes.Collections.AutowireTestSet, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestDictionary"
|
||||
type="Spring.Objects.Factory.Attributes.Collections.AutowireTestDictionary, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestDictionaryFail"
|
||||
type="Spring.Objects.Factory.Attributes.Collections.AutowireTestDictionaryFail, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
<object id="AutowireTestQualifier"
|
||||
type="Spring.Objects.Factory.Attributes.Collections.AutowireTestQualifier, Spring.Core.Tests"
|
||||
lazy-init="true" />
|
||||
|
||||
</objects>
|
||||
@@ -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();
|
||||
|
||||
@@ -73,6 +73,11 @@ namespace Spring.Objects.Factory
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public bool IsPrimary
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public string ParentName
|
||||
{
|
||||
get { return null; }
|
||||
|
||||
@@ -317,6 +317,15 @@
|
||||
<Compile Include="HookableContextHandler.cs" />
|
||||
<Compile Include="Objects\ExpressionTestObject.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\PostConstructAttributeTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByTypeNormalTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByTypeFailTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireTestObjects.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByTypePrimaryTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByTypeNotRequiredTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByQualifierTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByQualifierAttributeTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByValueTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireCollectionTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\MyRequiredAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\PreDestroyAttributeTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\RequiredAttributeObjectPostProcessorTests.cs" />
|
||||
@@ -867,6 +876,15 @@
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithThreeRequiredPropertiesOmitted.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithAllRequiredPropertiesProvided.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithCustomAttribute.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByTypeNormalObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByTypeFailObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByTypePrimaryObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByTypeNotRequiredObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByQualifierObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByQualifierAttributeObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByValueObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByValueObjects.config" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\CollectionObjects.xml" />
|
||||
<Content Include="Spring.Core.Tests.dll.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
@@ -319,6 +319,15 @@
|
||||
<Compile Include="HookableContextHandler.cs" />
|
||||
<Compile Include="Objects\ExpressionTestObject.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\PostConstructAttributeTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByTypeNormalTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByTypeFailTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireTestObjects.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByTypePrimaryTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByTypeNotRequiredTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByQualifierTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByQualifierAttributeTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireByValueTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\AutowireCollectionTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\MyRequiredAttribute.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\PreDestroyAttributeTests.cs" />
|
||||
<Compile Include="Objects\Factory\Attributes\RequiredAttributeObjectPostProcessorTests.cs" />
|
||||
@@ -870,6 +879,15 @@
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithThreeRequiredPropertiesOmitted.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithAllRequiredPropertiesProvided.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\RequiredWithCustomAttribute.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByTypeNormalObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByTypeFailObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByTypePrimaryObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByTypeNotRequiredObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByQualifierObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByQualifierAttributeObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByValueObjects.xml" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\ByValueObjects.config" />
|
||||
<EmbeddedResource Include="Objects\Factory\Attributes\CollectionObjects.xml" />
|
||||
<Content Include="Spring.Core.Tests.dll.config" />
|
||||
<EmbeddedResource Include="Resources\Spring.Context.Tests.de-AT.resx" />
|
||||
<EmbeddedResource Include="Resources\Spring.Context.Tests.de.resx" />
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
<include name="**/*.vb" />
|
||||
<include name="**/*.properties" />
|
||||
<include name="**/*.xml" />
|
||||
<include name="**/*.config" />
|
||||
<!--
|
||||
<include name="**/SimpleAppContext.xml" />
|
||||
<include name="**/Factory/Attributes/*.xml" />
|
||||
|
||||
Reference in New Issue
Block a user