Ejemplo n.º 1
0
        internal ConstructorData GetConstructorData(IList<ConstructorInfo> constructors, Arguments args)
        {
            /*
                0:  No Constructors : Throw Ex
                1:  Only Default Constructor, No Arguments : Invoke()
                2:  Only Default Constructor, Arguments supplied : Invoke()
                3:  Onlt Parameterised, No Arguments : Throw Ex()
                4:  Only Parameterised, Constructors with all args = 0 : Throw Ex
                5:  Only Parameterised, Constructors with exact args : Invoke()
                6:  Only Parameterised, Constructors with all args, registry cannot fill remainder : Throw Ex
                7:  Only Parameterised, Constructors with all args, registry can fill remainder : Invoke()
                8:  Mixed Constructors, No Arguments : Invoke()
                9:  Mixed Constructors, Constructors with all args = 0 : Throw Ex
                10: Mixed Constructors, Constructors with exact args : Invoke()
                11: Mixed Constructors, Constructors with all args, registry cannot fill remainder : Throw Ex
                12: Mixed Constructors, Constructors with all args, registry can fill remainder : Invoke()
            */

            //none
            if (constructors.Count == 0)
            {
                throw new ConstructorException();
            }

            //only Default
            if (constructors.All(c => c.GetParameters().Count() == 0))
            {

                //1
                if (args.Count != 0)
                {
                    throw new ConstructorException();
                }

                //2
                return new ConstructorData(constructors.First());
            }

            //Only Parameterised
            if (constructors.All(c => c.GetParameters().Count() > 0))
            {

                //3
                if (args.Count == 0)
                {
                    throw new ConstructorException();
                }

                //4
                if (!constructors.Any(c => args.All(a => c.GetParameters().Contains(a))))
                {
                    throw new ConstructorException();
                }

                var withAll = constructors.Where(c => args.All(a => c.GetParameters().Contains(a)));
                var exact = withAll.Where(c => c.GetParameters().Count() == args.Count);

                //5
                if (exact.Count() > 0)
                {
                    var best = GetBestMatch(exact, args, null);

                    return new ConstructorData(best.Constructor, best.Arguments);
                }

                //6
                var unmatchedArgs = GetUnmatchedArgs(withAll, args);
                if (!unmatchedArgs.Any(u => _registry.ContainsAll(u.Value.Select(p => p.ParameterType))))
                {
                    throw new ConstructorException();
                }

                //7
                var bestMatch = GetBestMatch(exact, args, unmatchedArgs);
                return new ConstructorData(bestMatch.Constructor , bestMatch.Arguments);
            }

            //mixed
            if (constructors.Any(c => c.GetParameters().Count() > 0) && constructors.Any(c => c.GetParameters().Count() == 0))
            {

                //8
                if (args.Count == 0)
                {
                    var ctor = constructors.First(c => c.GetParameters().Count() == 0);
                    return new ConstructorData(ctor);
                }

                //9
                if (!constructors.Any(c => args.All(a => c.GetParameters().Contains(a))))
                {
                    throw new ConstructorException();
                }

                var withAll = constructors.Where(c => args.All(a => c.GetParameters().Contains(a)));
                var exact = withAll.Where(c => c.GetParameters().Count() == args.Count);

                //10
                if (exact.Count() > 0)
                {
                    var best = GetBestMatch(exact, args, new Dictionary<ConstructorInfo, IList<ParameterInfo>>()  );
                    return new ConstructorData(best.Constructor, best.Arguments);
                }

                //11
                var unmatchedArgs = GetUnmatchedArgs(withAll, args);
                if (!unmatchedArgs.Any(u => _registry.ContainsAll(u.Value.Select(p => p.ParameterType))))
                {
                    throw new ConstructorException();
                }

                //12
                var bestMatch = GetBestMatch(exact, args, unmatchedArgs);
                return new ConstructorData(bestMatch.Constructor, bestMatch.Arguments);
            }

            throw new ConstructorException();
        }