Example #1
0
        /// <summary>
        /// Resolves the supplied generic <paramref name="typeName"/> to a
        /// <see cref="System.Type"/> instance.
        /// </summary>
        /// <param name="typeName">
        /// The unresolved (possibly generic) name of a <see cref="System.Type"/>.
        /// </param>
        /// <returns>
        /// A resolved <see cref="System.Type"/> instance.
        /// </returns>
        /// <exception cref="System.TypeLoadException">
        /// If the supplied <paramref name="typeName"/> could not be resolved
        /// to a <see cref="System.Type"/>.
        /// </exception>
        public override Type Resolve(string typeName)
        {
            if (StringUtils.IsNullOrEmpty(typeName))
            {
                throw BuildTypeLoadException(typeName);
            }
            GenericArgumentsHolder genericInfo = new GenericArgumentsHolder(typeName);
            Type type = null;

            try
            {
                if (genericInfo.ContainsGenericArguments)
                {
                    type = TypeResolutionUtils.ResolveType(genericInfo.GenericTypeName);
                    if (!genericInfo.IsGenericDefinition)
                    {
                        string[] unresolvedGenericArgs = genericInfo.GetGenericArguments();
                        Type[]   genericArgs           = new Type[unresolvedGenericArgs.Length];
                        for (int i = 0; i < unresolvedGenericArgs.Length; i++)
                        {
                            genericArgs[i] = TypeResolutionUtils.ResolveType(unresolvedGenericArgs[i]);
                        }
                        type = type.MakeGenericType(genericArgs);
                    }
                    if (genericInfo.IsArrayDeclaration)
                    {
                        typeName = string.Format("{0}{1},{2}", type.FullName, genericInfo.GetArrayDeclaration(), type.Assembly.FullName);
                        type     = null;
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex is TypeLoadException)
                {
                    throw;
                }
                throw BuildTypeLoadException(typeName, ex);
            }

            if (type == null)
            {
                type = base.Resolve(typeName);
            }

            return(type);
        }
        /// <summary>
        /// Resolves the supplied generic <paramref name="typeName"/> to a
        /// <see cref="System.Type"/> instance.
        /// </summary>
        /// <param name="typeName">
        /// The unresolved (possibly generic) name of a <see cref="System.Type"/>.
        /// </param>
        /// <returns>
        /// A resolved <see cref="System.Type"/> instance.
        /// </returns>
        /// <exception cref="System.TypeLoadException">
        /// If the supplied <paramref name="typeName"/> could not be resolved
        /// to a <see cref="System.Type"/>.
        /// </exception>
        public override Type Resolve(string typeName)
        {
            if (StringUtils.IsNullOrEmpty(typeName))
            {
                throw BuildTypeLoadException(typeName);
            }
            GenericArgumentsHolder genericInfo = new GenericArgumentsHolder(typeName);
            Type type = null;
            try
            {
                if (genericInfo.ContainsGenericArguments)
                {
                    type = TypeResolutionUtils.ResolveType(genericInfo.GenericTypeName);
                    if (!genericInfo.IsGenericDefinition)
                    {
                        string[] unresolvedGenericArgs = genericInfo.GetGenericArguments();
                        Type[] genericArgs = new Type[unresolvedGenericArgs.Length];
                        for (int i = 0; i < unresolvedGenericArgs.Length; i++)
                        {
                            genericArgs[i] = TypeResolutionUtils.ResolveType(unresolvedGenericArgs[i]);
                        }
                        type = type.MakeGenericType(genericArgs);
                    }
                    if (genericInfo.IsArrayDeclaration)
                    {
                        typeName = string.Format("{0}{1},{2}", type.FullName, genericInfo.GetArrayDeclaration(), type.Assembly.FullName);
                        type = null;
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex is TypeLoadException)
                {
                    throw;
                }
                throw BuildTypeLoadException(typeName, ex);
            }

            if (type == null)
            {
                type = base.Resolve(typeName);
            }

            return type;
        }
        /// <summary>
        /// Instantiate an object instance using a named factory method.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The method may be static, if the <paramref name="definition"/>
        /// parameter specifies a class, rather than a
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/> instance, or an
        /// instance variable on a factory object itself configured using Dependency
        /// Injection.
        /// </p>
        /// <p>
        /// Implementation requires iterating over the static or instance methods
        /// with the name specified in the supplied <paramref name="definition"/>
        /// (the method may be overloaded) and trying to match with the parameters.
        /// We don't have the types attached to constructor args, so trial and error
        /// is the only way to go here.
        /// </p>
        /// </remarks>
        /// <param name="name">
        /// The name associated with the supplied <paramref name="definition"/>.
        /// </param>
        /// <param name="definition">
        /// The definition describing the instance that is to be instantiated.
        /// </param>
        /// <param name="arguments">
        /// Any arguments to the factory method that is to be invoked.
        /// </param>
        /// <returns>
        /// The result of the factory method invocation (the instance).
        /// </returns>
        public virtual IObjectWrapper InstantiateUsingFactoryMethod(string name, RootObjectDefinition definition, object[] arguments)
        {
            ObjectWrapper wrapper = new ObjectWrapper();
            Type factoryClass = null;
            bool isStatic = true;


            ConstructorArgumentValues cargs = definition.ConstructorArgumentValues;
            ConstructorArgumentValues resolvedValues = new ConstructorArgumentValues();
            int expectedArgCount = 0;

            // we don't have arguments passed in programmatically, so we need to resolve the
            // arguments specified in the constructor arguments held in the object definition...
            if (arguments == null || arguments.Length == 0)
            {
                expectedArgCount = cargs.ArgumentCount;
                ResolveConstructorArguments(name, definition, wrapper, cargs, resolvedValues);
            }
            else
            {
                // if we have constructor args, don't need to resolve them...
                expectedArgCount = arguments.Length;
            }


            if (StringUtils.HasText(definition.FactoryObjectName))
            {
                // it's an instance method on the factory object's class...
                factoryClass = objectFactory.GetObject(definition.FactoryObjectName).GetType();
                isStatic = false;
            }
            else
            {
                // it's a static factory method on the object class...
                factoryClass = definition.ObjectType;
            }

            GenericArgumentsHolder genericArgsInfo = new GenericArgumentsHolder(definition.FactoryMethodName);
            IList<MethodInfo> factoryMethodCandidates = FindMethods(genericArgsInfo.GenericMethodName, expectedArgCount, isStatic, factoryClass);

            bool autowiring = (definition.AutowireMode == AutoWiringMode.Constructor);

            // try all matching methods to see if they match the constructor arguments...
            for (int i = 0; i < factoryMethodCandidates.Count; i++)
            {
                MethodInfo factoryMethodCandidate = factoryMethodCandidates[i];
                if (genericArgsInfo.ContainsGenericArguments)
                {
                    string[] unresolvedGenericArgs = genericArgsInfo.GetGenericArguments();
                    if (factoryMethodCandidate.GetGenericArguments().Length != unresolvedGenericArgs.Length)
                        continue;

                    Type[] paramTypes = new Type[unresolvedGenericArgs.Length];
                    for (int j = 0; j < unresolvedGenericArgs.Length; j++)
                    {
                        paramTypes[j] = TypeResolutionUtils.ResolveType(unresolvedGenericArgs[j]);
                    }
                    factoryMethodCandidate = factoryMethodCandidate.MakeGenericMethod(paramTypes);
                }
                if (arguments == null || arguments.Length == 0)
                {
                    Type[] paramTypes = ReflectionUtils.GetParameterTypes(factoryMethodCandidate.GetParameters());
                    // try to create the required arguments...
                    UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData = null;
                    ArgumentsHolder args = CreateArgumentArray(name, definition, resolvedValues, wrapper, paramTypes,
                                                               factoryMethodCandidate, autowiring, out unsatisfiedDependencyExceptionData);
                    if (args == null)
                    {
                        arguments = null;
                        // if we failed to match this method, keep
                        // trying new overloaded factory methods...
                        continue;
                    }
                    else
                    {
                        arguments = args.arguments;
                    }
                }

                // if we get here, we found a usable candidate factory method - check, if arguments match
                //arguments = (arguments.Length == 0 ? null : arguments);
                if (ReflectionUtils.GetMethodByArgumentValues(new MethodInfo[] { factoryMethodCandidate }, arguments) == null)
                {
                    continue;
                }

                object objectInstance = instantiationStrategy.Instantiate(definition, name, objectFactory, factoryMethodCandidate, arguments);
                wrapper.WrappedInstance = objectInstance;

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format(CultureInfo.InvariantCulture, "Object '{0}' instantiated via factory method [{1}].", name, factoryMethodCandidate));
                }

                #endregion

                return wrapper;
            }



            // if we get here, we didn't match any method...
            throw new ObjectDefinitionStoreException(
                    string.Format(CultureInfo.InvariantCulture, "Cannot find matching factory method '{0} on Type [{1}].", definition.FactoryMethodName,
                                  factoryClass));
        }
        /// <summary>
        /// Determines the <see cref="System.Type"/> of the object defined
        /// by the supplied object <paramref name="definition"/>. 
        /// </summary>
        /// <param name="objectName">
        /// The name associated with the supplied object <paramref name="definition"/>.
        /// </param>
        /// <param name="definition">
        /// The <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>
        /// that the <see cref="System.Type"/> is to be determined for. 
        /// </param>
        /// <returns>
        /// The <see cref="System.Type"/> of the object defined by the supplied
        /// object <paramref name="definition"/>; or <see lang="null"/> if the
        /// <see cref="System.Type"/> cannot be determined.
        /// </returns>
        protected override Type GetTypeForFactoryMethod(string objectName, RootObjectDefinition definition)
        {
            Type factoryType = null;
            bool isStatic = true;

            if (StringUtils.HasText(definition.FactoryObjectName))
            {
                // check declared factory method return type on factory type...
                factoryType = GetType(definition.FactoryObjectName);
                isStatic = false;
            }
            else
            {
                factoryType = ResolveObjectType(definition, objectName);
            }
            if (factoryType == null)
            {
                return null;
            }

            // If all factory methods have the same return type, return that type.
            // Can't clearly figure out exact method due to type converting / autowiring!
            int minNrOfArgs = definition.ConstructorArgumentValues.GenericArgumentValues.Count;
            MethodInfo[] candidates = factoryType.GetMethods();
            ISet returnTypes = new HybridSet();
            foreach (MethodInfo factoryMethod in candidates)
            {
#if NET_2_0
                GenericArgumentsHolder genericArgsInfo = new GenericArgumentsHolder(definition.FactoryMethodName);
                if (factoryMethod.IsStatic == isStatic && factoryMethod.Name.Equals(genericArgsInfo.GenericMethodName)
                    && ReflectionUtils.GetParameterTypes(factoryMethod).Length >= minNrOfArgs
                    && factoryMethod.GetGenericArguments().Length == genericArgsInfo.GetGenericArguments().Length)
                {
                    if (genericArgsInfo.ContainsGenericArguments)
                    {
                        string[] unresolvedGenericArgs = genericArgsInfo.GetGenericArguments();
                        Type[] genericArgs = new Type[unresolvedGenericArgs.Length];
                        for (int j = 0; j < unresolvedGenericArgs.Length; j++)
                        {
                            genericArgs[j] = TypeResolutionUtils.ResolveType(unresolvedGenericArgs[j]);
                        }
                        returnTypes.Add(factoryMethod.MakeGenericMethod(genericArgs).ReturnType);
                    }
                    else
                    {
                        returnTypes.Add(factoryMethod.ReturnType);
                    }
                }
#else
                if (factoryMethod.IsStatic == isStatic && factoryMethod.Name.Equals(definition.FactoryMethodName)
                    && ReflectionUtils.GetParameterTypes(factoryMethod).Length >= minNrOfArgs)
                {
                    returnTypes.Add(factoryMethod.ReturnType);
                }
#endif
            }
            if (returnTypes.Count == 1)
            {
                // clear return type found: all factory methods return same type...
                return (Type)ObjectUtils.EnumerateFirstElement(returnTypes);
            }

            // ambiguous return types found: return null to indicate "not determinable"...
            return null;
        }
Example #5
0
		/// <summary>
		/// Searches for and returns the method that is to be invoked.
		/// </summary>
		/// <remarks>
		/// The return value of this method call will subsequently be returned from the
		/// <see cref="Spring.Objects.Support.MethodInvoker.GetPreparedMethod()"/>.
		/// </remarks>
		/// <returns>The method that is to be invoked.</returns>
		/// <exception cref="System.MissingMethodException">
		/// If no method could be found.
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// If more than one method was found.
		/// </exception>
        protected virtual MethodInfo FindTheMethodToInvoke()
        {
            MethodInfo theMethod = null;
            Type targetType = (TargetObject != null) ? TargetObject.GetType() : TargetType;
            GenericArgumentsHolder genericInfo = new GenericArgumentsHolder(TargetMethod);

            // if we don't have any named arguments, we can try to get the exact method first...
			if (NamedArguments.Count == 0)
			{
                ComposedCriteria searchCriteria = new ComposedCriteria();
                searchCriteria.Add(new MethodNameMatchCriteria(genericInfo.GenericMethodName));
                searchCriteria.Add(new MethodParametersCountCriteria(ArgumentCount));
                searchCriteria.Add(new MethodGenericArgumentsCountCriteria(genericInfo.GetGenericArguments().Length));
                searchCriteria.Add(new MethodArgumentsCriteria(Arguments));

                MemberInfo[] matchingMethods = targetType.FindMembers(
                    MemberTypes.Method,
                    MethodSearchingFlags,
                    new MemberFilter(new CriteriaMemberFilter().FilterMemberByCriteria),
                    searchCriteria);

                if (matchingMethods != null && matchingMethods.Length == 1)
                {
                    theMethod = matchingMethods[0] as MethodInfo;
                }
			}
            if (theMethod == null)
            {
                // search for a method with a matching signature... 
                ComposedCriteria searchCriteria = new ComposedCriteria();
                searchCriteria.Add(new MethodNameMatchCriteria(genericInfo.GenericMethodName));
                searchCriteria.Add(new MethodParametersCountCriteria(ArgumentCount));
                searchCriteria.Add(new MethodGenericArgumentsCountCriteria(genericInfo.GetGenericArguments().Length));

                MemberInfo[] matchingMethods = targetType.FindMembers(
                    MemberTypes.Method,
                    MethodSearchingFlags,
                    new MemberFilter(new CriteriaMemberFilter().FilterMemberByCriteria),
                    searchCriteria);

                if (matchingMethods.Length == 0)
                {
                    throw new MissingMethodException(targetType.Name, TargetMethod);
                }
                if (matchingMethods.Length > 1)
                {
                    throw new ArgumentException(string.Format(
                        CultureInfo.InvariantCulture,
                        "Unable to determine which exact method to call; found '{0}' matches.",
                        matchingMethods.Length));
                }
                theMethod = matchingMethods[0] as MethodInfo;
            }

            if (genericInfo.ContainsGenericArguments)
            {
                string[] unresolvedGenericArgs = genericInfo.GetGenericArguments();
                Type[] genericArgs = new Type[unresolvedGenericArgs.Length];
                for (int j = 0; j < unresolvedGenericArgs.Length; j++)
                {
                    genericArgs[j] = TypeResolutionUtils.ResolveType(unresolvedGenericArgs[j]);
                }
                theMethod = theMethod.MakeGenericMethod(genericArgs);
            }

            return theMethod;
        }