public void ParameterReplaceVisitorTest()
        {
            var p1 = Expression.Parameter(typeof(int));

            var param = new Builder.ParameterReplaceVisitor(p1, p1);

            Expression <Func <int, object> > p = (a) => null;

            param.Visit(p);
            param.Visit(p1);

            Assert.AreNotEqual(param, null);
        }
        public static Expression <Func <T, object> > CombineSelectorsToNewObject <T>(List <FieldDefinition <T> > groups,
                                                                                     out Type type)
        {
            var fieldsForGroup = groups.ToDictionary(@group => @group.Name, @group => GetNullableType(@group.Type));

            var createdType = GetDynamicType(fieldsForGroup, typeof(T));

            type = createdType;

            var param = Expression.Parameter(typeof(T), "x");

            var arguments = new List <Expression>();

            foreach (var @group in groups)
            {
                var replace   = new ParameterReplaceVisitor(@group.Selector.Parameters[0], param);
                var fieldName = SanitizeCSharpIdentifier(@group.Name);
                var property  = createdType.GetField(@group.Name);
                if (property == null)
                {
                    throw new ApplicationException(string.Format("Could not find field {0} for type {1}.", fieldName,
                                                                 createdType));
                }
                var replacedParamExpression = replace.Visit(@group.Selector.Body);
                if (replacedParamExpression == null)
                {
                    throw new ApplicationException(string.Format("Could Visit and Convert expression: {0}",
                                                                 @group.Selector));
                }

                replacedParamExpression = Expression.Convert(replacedParamExpression, GetNullableType(@group.Type));
                arguments.Add(replacedParamExpression);
            }

            var ctor = createdType.GetConstructor(fieldsForGroup.Select(a => a.Value).ToArray());

            if (ctor == null)
            {
                throw new ApplicationException(string.Format("Could not get ctor for created type: {0}, with args: {1}",
                                                             createdType,
                                                             string.Join <Type>(",", fieldsForGroup.Select(a => a.Value).ToArray())
                                                             ));
            }

            var ctorExpr = Expression.New(ctor, arguments.ToArray());

            return(Expression.Lambda <Func <T, object> >(ctorExpr, param));
        }
        public static Expression <Func <T, object> > CombineSelectorsToNewObject <T>(List <FieldDefinition <T> > selectors, Type createdType)
        {
            var param = Expression.Parameter(typeof(T), "x");

            var arguments = new List <Expression>();

            foreach (var selector in selectors)
            {
                var replace   = new ParameterReplaceVisitor(selector.Selector.Parameters[0], param);
                var fieldName = SanitizeCSharpIdentifier(selector.Name);
                var property  = createdType.GetField(fieldName);
                if (property == null)
                {
                    throw new ApplicationException($"Could not find field {fieldName} for type {createdType}.");
                }
                var replacedParamExpression = replace.Visit(selector.Selector.Body);
                if (replacedParamExpression == null)
                {
                    throw new ApplicationException($"Could Visit and Convert expression: {selector.Selector}");
                }

                replacedParamExpression = Expression.Convert(replacedParamExpression, GetNullableType(selector.Type));
                arguments.Add(replacedParamExpression);
            }

            var ctor = createdType.GetConstructor(selectors.Select(a => a.Type).ToArray());

            if (ctor == null)
            {
                throw new ApplicationException(
                          $"Could not get ctor for created type: {createdType}, with args: {string.Join<Type>(",", selectors.Select(a => a.Type).ToArray())}");
            }

            var ctorExpr = Expression.New(ctor, arguments.ToArray());

            return(Expression.Lambda <Func <T, object> >(ctorExpr, param));
        }