/// <summary>
        /// Returns the list of columns the materializer would like to have.
        /// </summary>
        /// <returns></returns>
        public override IReadOnlyList <string> DesiredColumns()
        {
            if (ConstructorSignature == null)
            {
                return(ObjectMetadata.ColumnsFor);
            }

            var desiredType = typeof(TObject);
            var constructor = ObjectMetadata.Constructors.Find(ConstructorSignature);

            if (constructor == null)
            {
                var types = string.Join(", ", ConstructorSignature.Select(t => t.Name));
                throw new MappingException($"Cannot find a constructor on {desiredType.Name} with the types [{types}]");
            }

            return(constructor.ParameterNames);
        }
Esempio n. 2
0
        /// <summary>
        /// Create an instance of <paramref name="type"/> using constructor with four argument. First matching constructor is used.
        /// </summary>
        /// <typeparam name="Arg1T">First argument type.</typeparam>
        /// <typeparam name="Arg2T">Second argument type.</typeparam>
        /// <typeparam name="Arg3T">Third argument type.</typeparam>
        /// <typeparam name="Arg4T">Forth argument type.</typeparam>
        /// <param name="type">Type of object to create.</param>
        /// <param name="arg1">Value of first argument.</param>
        /// <param name="arg2">Value for second argument.</param>
        /// <param name="arg3">Value for third argument.</param>
        /// <param name="arg4">Value for forth argument.</param>
        /// <param name="argCount">Number of arguments.</param>
        /// <returns>An instance of <paramref name="type"/>.</returns>
        private static object CreateInstance <Arg1T, Arg2T, Arg3T, Arg4T>(Type type, Arg1T arg1, Arg2T arg2, Arg3T arg3, Arg4T arg4, int argCount)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (argCount < 1 || argCount > 4)
            {
                throw new ArgumentOutOfRangeException("argCount");
            }

            var signature = new ConstructorSignature(type,
                                                     typeof(Arg1T), argCount > 1 ?
                                                     typeof(Arg2T) : null, argCount > 2 ?
                                                     typeof(Arg3T) : argCount > 3 ?
                                                     typeof(Arg4T) : null);

#if !NETSTANDARD
            var typeInfo     = type;
            var constructors = typeInfo.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#else
            var typeInfo     = type.GetTypeInfo();
            var constructors = typeInfo.DeclaredConstructors.ToList();
#endif
            var constructor = default(Delegate);
            lock (CustomConstructorCache)
            {
                if (CustomConstructorCache.TryGetValue(signature, out constructor) == false)
                {
                    var foundCtr = default(ConstructorInfo);

                    foreach (var constructorInfo in constructors)
                    {
                        var ctrParams = constructorInfo.GetParameters();
                        if (ctrParams.Length != argCount)
                        {
                            continue;
                        }
                        if (argCount > 0 && IsAssignableFrom(ctrParams[0].ParameterType, typeof(Arg1T)) == false)
                        {
                            continue;
                        }
                        if (argCount > 1 && IsAssignableFrom(ctrParams[1].ParameterType, typeof(Arg2T)) == false)
                        {
                            continue;
                        }
                        if (argCount > 2 && IsAssignableFrom(ctrParams[2].ParameterType, typeof(Arg3T)) == false)
                        {
                            continue;
                        }
                        if (argCount > 3 && IsAssignableFrom(ctrParams[3].ParameterType, typeof(Arg4T)) == false)
                        {
                            continue;
                        }

                        foundCtr = constructorInfo;
                        break;
                    }

                    if (foundCtr != null)
                    {
                        var ctrParameters = foundCtr.GetParameters();
                        var arg1Param     = Expression.Parameter(typeof(Arg1T), "arg1");
                        var arg2Param     = Expression.Parameter(typeof(Arg2T), "arg2");
                        var arg3Param     = Expression.Parameter(typeof(Arg3T), "arg3");
                        var arg4Param     = Expression.Parameter(typeof(Arg4T), "arg4");
                        switch (argCount)
                        {
                        case 1:
                            constructor = Expression.Lambda <Func <Arg1T, object> >
                                          (
                                Expression.Convert(
                                    Expression.New(
                                        foundCtr,
                                        Expression.Convert(arg1Param, ctrParameters[0].ParameterType)),
                                    typeof(object)
                                    ),
                                arg1Param
                                          ).Compile();
                            break;

                        case 2:
                            constructor = Expression.Lambda <Func <Arg1T, Arg2T, object> >
                                          (
                                Expression.Convert(
                                    Expression.New(
                                        foundCtr,
                                        Expression.Convert(arg1Param, ctrParameters[0].ParameterType),
                                        Expression.Convert(arg2Param, ctrParameters[1].ParameterType)),
                                    typeof(object)
                                    ),
                                arg1Param,
                                arg2Param
                                          ).Compile();
                            break;

                        case 3:
                            constructor = Expression.Lambda <Func <Arg1T, Arg2T, Arg3T, object> >
                                          (
                                Expression.Convert(
                                    Expression.New(
                                        foundCtr,
                                        Expression.Convert(arg1Param, ctrParameters[0].ParameterType),
                                        Expression.Convert(arg2Param, ctrParameters[1].ParameterType),
                                        Expression.Convert(arg3Param, ctrParameters[2].ParameterType)),
                                    typeof(object)
                                    ),
                                arg1Param,
                                arg2Param,
                                arg3Param
                                          ).Compile();
                            break;

                        case 4:
                            constructor = Expression.Lambda <Func <Arg1T, Arg2T, Arg3T, Arg4T, object> >
                                          (
                                Expression.Convert(
                                    Expression.New(
                                        foundCtr,
                                        Expression.Convert(arg1Param, ctrParameters[0].ParameterType),
                                        Expression.Convert(arg2Param, ctrParameters[1].ParameterType),
                                        Expression.Convert(arg3Param, ctrParameters[2].ParameterType),
                                        Expression.Convert(arg4Param, ctrParameters[3].ParameterType)),
                                    typeof(object)
                                    ),
                                arg1Param,
                                arg2Param,
                                arg3Param,
                                arg4Param
                                          ).Compile();
                            break;
                        }
                    }

                    CustomConstructorCache[signature] = constructor;
                }
            }

            var instance = default(object);
            // create instance
            switch (argCount)
            {
            case 1:
                if (constructor == null)
                {
                    throw new ArgumentException(string.Format("Type '{0}' does not contains constructor with signature 'ctr({1})'.", type, typeof(Arg1T).Name), "type");
                }
                instance = ((Func <Arg1T, object>)constructor)(arg1);
                break;

            case 2:
                if (constructor == null)
                {
                    throw new ArgumentException(string.Format("Type '{0}' does not contains constructor with signature 'ctr({1}, {2})'.", type, typeof(Arg1T).Name, typeof(Arg2T).Name), "type");
                }
                instance = ((Func <Arg1T, Arg2T, object>)constructor)(arg1, arg2);
                break;

            case 3:
                if (constructor == null)
                {
                    throw new ArgumentException(string.Format("Type '{0}' does not contains constructor with signature 'ctr({1}, {2}, {3})'.", type, typeof(Arg1T).Name, typeof(Arg2T).Name, typeof(Arg3T).Name), "type");
                }
                instance = ((Func <Arg1T, Arg2T, Arg3T, object>)constructor)(arg1, arg2, arg3);
                break;

            case 4:
                if (constructor == null)
                {
                    throw new ArgumentException(string.Format("Type '{0}' does not contains constructor with signature 'ctr({1}, {2}, {3}, {4})'.", type, typeof(Arg1T).Name, typeof(Arg2T).Name, typeof(Arg3T).Name, typeof(Arg4T).Name), "type");
                }
                instance = ((Func <Arg1T, Arg2T, Arg3T, Arg4T, object>)constructor)(arg1, arg2, arg3, arg4);
                break;
            }

            return(instance);
        }