PageRenderTime 70ms CodeModel.GetById 30ms app.highlight 5ms RepoModel.GetById 15ms app.codeStats 0ms

/src/LinFu.IoC/Configuration/Resolvers/MethodFinderFromContainer.cs

http://github.com/philiplaureano/LinFu
C# | 106 lines | 57 code | 13 blank | 36 comment | 4 complexity | 9d3e288600412901c15ee19fe8a95d32 MD5 | raw file
  1using System.Collections.Generic;
  2using System.Linq;
  3using System.Reflection;
  4using LinFu.Finders;
  5using LinFu.Finders.Interfaces;
  6using LinFu.IoC.Configuration.Interfaces;
  7using LinFu.IoC.Interfaces;
  8
  9namespace LinFu.IoC.Configuration.Resolvers
 10{
 11    /// <summary>
 12    ///     A <see cref="MethodFinder{TMethod}" /> type that uses a <see cref="IServiceContainer" />
 13    ///     instance to find a method with the most resolvable parameters.
 14    /// </summary>
 15    /// <typeparam name="TMethod">The method type that will be searched.</typeparam>
 16    public class MethodFinderFromContainer<TMethod> : MethodFinder<TMethod>, IMethodFinderWithContainer<TMethod>,
 17        IInitialize
 18        where TMethod : MethodBase
 19    {
 20        /// <summary>
 21        ///     Initializes the target with the host container.
 22        /// </summary>
 23        /// <param name="container">The host <see cref="IServiceContainer" /> instance.</param>
 24        public void Initialize(IServiceContainer container)
 25        {
 26            Container = container;
 27        }
 28
 29
 30        /// <summary>
 31        ///     Gets the value indicating the service container that will be used in the
 32        ///     method search.
 33        /// </summary>
 34        public IServiceContainer Container { get; private set; }
 35
 36
 37        /// <summary>
 38        ///     Examines a <see cref="ConstructorInfo" /> instance
 39        ///     and determines if it can be instantiated with the services embedded in
 40        ///     the target <paramref name="container" />.
 41        /// </summary>
 42        /// <param name="fuzzyItem">The <see cref="FuzzyItem{T}" /> that represents the constructor to be examined.</param>
 43        /// <param name="container">The container that contains the services that will be used to instantiate the target type.</param>
 44        /// <param name="maxIndex">
 45        ///     Indicates the index that
 46        ///     marks the point where the user-supplied arguments begin.
 47        /// </param>
 48        private static void CheckParameters(IFuzzyItem<TMethod> fuzzyItem,
 49            IServiceContainer container, int maxIndex)
 50        {
 51            var constructor = fuzzyItem.Item;
 52            var currentIndex = 0;
 53            foreach (var param in constructor.GetParameters())
 54            {
 55                if (currentIndex == maxIndex)
 56                    break;
 57
 58                var parameterType = param.ParameterType;
 59                var criteria = new Criteria<TMethod> {Type = CriteriaType.Critical, Weight = 1};
 60
 61                // The type must either be an existing service
 62                // or a list of services that can be created from the container
 63                var predicate = parameterType.MustExistInContainer()
 64                    .Or(parameterType.ExistsAsServiceArray())
 65                    .Or(parameterType.ExistsAsEnumerableSetOfServices());
 66
 67                criteria.Predicate = currentConstructor => predicate(container);
 68                fuzzyItem.Test(criteria);
 69
 70                currentIndex++;
 71            }
 72        }
 73
 74        /// <summary>
 75        ///     Adds additional <see cref="ICriteria{T}" /> to the fuzzy search list.
 76        /// </summary>
 77        /// <param name="methods">The list of methods to rank.</param>
 78        /// <param name="finderContext">The <see cref="IMethodFinderContext" /> that describes the target method.</param>
 79        protected override void Rank(IList<IFuzzyItem<TMethod>> methods, IMethodFinderContext finderContext)
 80        {
 81            var additionalArguments = finderContext.Arguments ?? new object[0];
 82            var argumentTypes = (from argument in additionalArguments
 83                let argumentType = argument == null ? typeof(object) : argument.GetType()
 84                select argumentType).ToList();
 85
 86            var argumentCount = argumentTypes.Count;
 87            foreach (var fuzzyItem in methods)
 88            {
 89                if (fuzzyItem.Confidence < 0)
 90                    continue;
 91
 92                // Check the constructor for any 
 93                // parameter types that might not exist
 94                // in the container and eliminate the
 95                // constructor as a candidate match if
 96                // that parameter type cannot be found
 97                var constructor = fuzzyItem.Item;
 98                var parameters = constructor.GetParameters();
 99                var parameterCount = parameters.Length;
100                var maxRelativeIndex = parameterCount - argumentCount;
101
102                CheckParameters(fuzzyItem, Container, maxRelativeIndex);
103            }
104        }
105    }
106}