Exemplo n.º 1
0
        public Expression <GenericPropertySetter> BuildGenericSetter(PropertyInfo propertyInfo)
        {
            var setMethod = ValidatePropertyAndGetAccessorMethod(propertyInfo, null, false);

            if (EnableCaching &&
                genericSetterCache.TryGetValue(propertyInfo, out var cachedLambda))
            {
                return((Expression <GenericPropertySetter>)cachedLambda);
            }

            var instanceParameter = Expression.Parameter(typeof(object), "instance");
            var inputParameters   = Expression.Parameter(typeof(object[]), "indexers");
            var valueParameter    = Expression.Parameter(typeof(object), "value");

            var methodCallParameters = propertyInfo.GetIndexParameters()
                                       .Select((x, i) => ExpressionEx.ConvertIfNeeded(
                                                   Expression.ArrayAccess(inputParameters, Expression.Constant(i)),
                                                   x.ParameterType))
                                       .Concat(new[] { ExpressionEx.ConvertIfNeeded(valueParameter, propertyInfo.PropertyType) });

            var invokerExpression =
                Expression.Call(
                    setMethod.IsStatic ? null : ExpressionEx.ConvertIfNeeded(instanceParameter, setMethod.DeclaringType),
                    setMethod,
                    methodCallParameters);

            var lambda = Expression.Lambda <GenericPropertySetter>(invokerExpression, new[] { instanceParameter, valueParameter, inputParameters });

            if (EnableCaching)
            {
                genericSetterCache.TryAdd(propertyInfo, lambda);
            }

            return(lambda);
        }
Exemplo n.º 2
0
        private CompiledDynamicProjectionConfiguration Compile()
        {
            configuration.ProjectedType =
                configuration.ProjectedType ??
#if NETSTANDARD2_0
                throw new InvalidOperationException("Projected type not set. Dynamic type building in not supported in net standard.");
#else
                BuildProjectedType();
#endif
            configuration.Ctor = configuration.Ctor ?? FindMatchingConstructor();

            if (configuration.Ctor == null)
            {
                throw new InvalidOperationException($"No matching constructor found for type {configuration.ProjectedType.Name}");
            }

            var compiledMembers    = configuration.Members.Select(x => (Configuration: x, CompiledMember: CompileMember(x))).ToList();
            var compiledCtorParams = configuration.CtorParameters.Select(x => (Configuration: x, CompiledCtorParam: CompileCtorParameter(x))).ToList();

            var compiledMemberTargets    = compiledMembers.Select(x => new CompiledMemberTargetConfiguration(x.CompiledMember, CompileMemberSource(x.CompiledMember, x.Configuration))).ToList();
            var compiledCtorParamTargets = compiledCtorParams.Select(x => new CompiledCtorParamTargetConfiguration(x.CompiledCtorParam, CompileCtorParameterSource(x.CompiledCtorParam, x.Configuration))).ToList();

            var ctorParameterAssignments =
                configuration.Ctor.GetParameters().Select(p =>
                                                          compiledCtorParamTargets
                                                          .Where(x => x.CtorParameter.ParameterInfo.Name == p.Name)
                                                          .Select(x => new CtorParameterAssignment(null, x.Source.SourceExpression))
                                                          .FirstOrDefault() ??
                                                          compiledMemberTargets
                                                          .Where(x => x.Member.ProjectionTarget == ProjectionTarget.CtorParameter && x.Member.CtorParameterName == p.Name)
                                                          .Select(x => new CtorParameterAssignment(x.Member.MemberInfo.Name, x.Source.SourceExpression))
                                                          .FirstOrDefault() ??
                                                          (p.HasDefaultValue
                                ? new CtorParameterAssignment(null, Expression.Constant(p.DefaultValue))
                                : throw new InvalidOperationException($"No source given for non optional constructor parameter {p.Name} on type {configuration.ProjectedType.Name}")))
                .ToList();

            var memberInitAssignments =
                compiledMemberTargets
                .Where(x => x.Member.ProjectionTarget == ProjectionTarget.Member)
                .Select(p => new MemberInitAssignment(
                            memberName:
                            p.Member.MemberInfo.Name,
                            memberAssignement:
                            Expression.Bind(
                                p.Member.MemberInfo,
                                ExpressionEx.ConvertIfNeeded(p.Source.SourceExpression, p.Member.MemberType))))
                .ToList();

            var defaultProjection = Expression.Lambda(
                Expression.MemberInit(
                    Expression.New(configuration.Ctor, ctorParameterAssignments.Select(x => x.SourceExpression)),
                    memberInitAssignments.Select(x => x.MemberAssignement)),
                configuration.It);

            return(new CompiledDynamicProjectionConfiguration(
                       configuration,
                       compiledCtorParamTargets,
                       compiledMemberTargets, memberInitAssignments, ctorParameterAssignments, defaultProjection));
        }
Exemplo n.º 3
0
        public Expression <Func <object, object> > BuildGenericGetter(FieldInfo fieldInfo)
        {
            ValidateField(fieldInfo, null);

            if (EnableCaching &&
                genericGetterCache.TryGetValue(fieldInfo, out var cachedLambda))
            {
                return((Expression <Func <object, object> >)cachedLambda);
            }

            var instanceParameter = Expression.Parameter(typeof(object), "instance");

            var invokerExpression =
                Expression.Field(
                    fieldInfo.IsStatic ? null : ExpressionEx.ConvertIfNeeded(instanceParameter, fieldInfo.DeclaringType),
                    fieldInfo);

            var body   = ExpressionEx.CastTypeSafe(invokerExpression, typeof(object));
            var lambda = Expression.Lambda <Func <object, object> >(body, instanceParameter);

            if (EnableCaching)
            {
                genericGetterCache.TryAdd(fieldInfo, lambda);
            }

            return(lambda);
        }
Exemplo n.º 4
0
        private static Expression BuildKeyValueSelectorExpression(Type entityType, List <PropertyInfo> keyProperties, out ParameterExpression entityParameterExpression, out Type keyValueType)
        {
            entityParameterExpression = Expression.Parameter(typeof(object));
            var convertedEntityTypeExpression = ExpressionEx.ConvertIfNeeded(entityParameterExpression, entityType);

            if (!keyProperties.Any())
            {
                keyProperties = entityType.GetProperties().ToList();
            }

            if (keyProperties.Count == 1)
            {
                var property = keyProperties.Single();
                keyValueType = property.PropertyType;
                return(Expression.Property(convertedEntityTypeExpression, property));
            }
            else
            {
                keyValueType = BuildKeyValueType(entityType, keyProperties);

                var keyValueTypeCtor = keyValueType.GetConstructors().First(x => x.GetParameters().Length > 0);

                return(Expression.New(
                           constructor: keyValueTypeCtor,
                           arguments: keyProperties
                           .Select(x => Expression.Property(convertedEntityTypeExpression, x))
                           .ToArray()
                           ));
            }
        }
        public Expression <GenericStaticInvoker> BuildGeneric(ConstructorInfo ctorInfo)
        {
            if (ctorInfo == null)
            {
                throw new ArgumentNullException(nameof(ctorInfo));
            }

            if (EnableCaching && genericCache.TryGetValue(ctorInfo, out var cachedLambda))
            {
                return((Expression <GenericStaticInvoker>)cachedLambda);
            }

            var inputParameters = Expression.Parameter(typeof(object[]), "parameters");

            var methodParameters     = ctorInfo.GetParameters();
            var methodCallParameters = methodParameters
                                       .Select((x, i) => ExpressionEx.ConvertIfNeeded(
                                                   Expression.ArrayAccess(inputParameters, Expression.Constant(i)),
                                                   x.ParameterType));

            var invokerExpression = Expression.New(
                ctorInfo,
                methodCallParameters);

            var body = ExpressionEx.CastTypeSafe(invokerExpression, typeof(object));

            var lambda = Expression.Lambda <GenericStaticInvoker>(body, new[] { inputParameters });

            if (EnableCaching)
            {
                genericCache.TryAdd(ctorInfo, lambda);
            }

            return(lambda);
        }
Exemplo n.º 6
0
        private static Expression BuildSetKeyConstructorExpression(Type keyType, Type keyValueType, Expression keyValueSelectorExpression)
        {
            var keyCtorSet = keyType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { keyValueType }, null);

            return(Expression.New(
                       constructor: keyCtorSet,
                       arguments: ExpressionEx.ConvertIfNeeded(keyValueSelectorExpression, keyValueType)));
        }
Exemplo n.º 7
0
        public static Func <object, object> BuildKeyValueSelector(Type type, IEnumerable <PropertyInfo> keyPropertiesEnumerable)
        {
            var keyProperties = keyPropertiesEnumerable is List <PropertyInfo> keyPropertiesList ? keyPropertiesList : keyPropertiesEnumerable.ToList();

            var selector = BuildKeyValueSelectorExpression(type, keyProperties, out var parameter, out var _);
            var body     = ExpressionEx.ConvertIfNeeded(selector, typeof(object));

            return(Expression.Lambda <Func <object, object> >(body, parameter).Compile());
        }
Exemplo n.º 8
0
        public Expression <Action <object, object> > BuildGenericSetter(FieldInfo fieldInfo)
        {
            ValidateField(fieldInfo, null);

            if (EnableCaching &&
                genericSetterCache.TryGetValue(fieldInfo, out var cachedLambda))
            {
                return((Expression <Action <object, object> >)cachedLambda);
            }

            var instanceParameter = Expression.Parameter(typeof(object), "instance");
            var value             = Expression.Parameter(typeof(object), "value");
            var castedInstance    = ExpressionEx.ConvertIfNeeded(instanceParameter, fieldInfo.DeclaringType);

            Expression <Action <object, object> > lambda;

            if (!fieldInfo.IsInitOnly)
            {
                lambda = Expression.Lambda <Action <object, object> >(
                    Expression.Assign(
                        Expression.Field(fieldInfo.IsStatic ? null : castedInstance, fieldInfo),
                        GetCastedValueExpression(value, fieldInfo.FieldType)),
                    instanceParameter, value);
            }
            else
            {
#if !NETSTANDARD2_0
                var m = Reflection.Emit.FieldAccessorMethodEmitter.GetFieldSetterMethod(fieldInfo, GenericTypeExtensions.GetActionGenericType(fieldInfo.DeclaringType, fieldInfo.FieldType));
                lambda = Expression.Lambda <Action <object, object> >(
                    Expression.Call(m, castedInstance, GetCastedValueExpression(value, fieldInfo.FieldType)),
                    instanceParameter, value);
#else
                throw new InvalidOperationException($"Field {fieldInfo.Name} is InitOnly and cannot be set.");
#endif
            }

            if (EnableCaching)
            {
                genericGetterCache.TryAdd(fieldInfo, lambda);
            }

            return(lambda);
        }
Exemplo n.º 9
0
        public LambdaExpression CreateSelector(Type ModelType, Type returnType = null, IEnumerable <string> includedProperties = null)
        {
            var inParam = Expression.Parameter(ModelType, "model");

            if (returnType == null)
            {
                returnType = GetReturnType("tmpDynamicDTO_" + random.Next().ToString());
            }

            var memberAssignments = new List <MemberAssignment>();

            foreach (var p in (includedProperties == null ? props : props.Where(x => includedProperties.Any(ip => StringComparer.OrdinalIgnoreCase.Compare(ip, x.TargetProperty ?? x.PropertyName) == 0))))
            {
                Expression memberExpression;

                var exp = p.SourceExpression;
                if (exp == null)
                {
                    memberExpression = Expression.Property(CreateMemberExpression(inParam, p.PropertyPath), p.PropertyName);
                }
                else
                {
                    var memberlambda = (LambdaExpression) new SelectorToExpressionVisitor().Modify(
                        exp,
                        exp.Parameters[0],
                        CreateMemberExpression(inParam, p.PropertyPath));

                    memberExpression = memberlambda.Body;
                }
                var targetProperty = returnType.GetProperty(p.TargetProperty);

                memberAssignments.Add(
                    Expression.Bind(
                        targetProperty,
                        ExpressionEx.ConvertIfNeeded(memberExpression, targetProperty.PropertyType)
                        ));
            }

            var init = Expression.MemberInit(Expression.New(returnType), memberAssignments);

            return(Expression.Lambda(init, inParam));
        }
Exemplo n.º 10
0
        public static Func <object, object> BuildKeySelector(Type entityType, IEnumerable <PropertyInfo> keyPropertiesEnumerable)
        {
            var keyProperties = keyPropertiesEnumerable is List <PropertyInfo> keyPropertiesList ? keyPropertiesList : keyPropertiesEnumerable.ToList();
            var valueSelectorExpression = BuildKeyValueSelectorExpression(entityType, keyProperties, out var entityParameterExpression, out var keyValueType);

            var keyType          = typeof(DomainKey <>).MakeGenericTypeCached(keyValueType);
            var entityExpression = ExpressionEx.ConvertIfNeeded(entityParameterExpression, entityType);

            var keySetCtorExpression   = BuildSetKeyConstructorExpression(keyType, keyValueType, valueSelectorExpression);
            var keyUnSetCtorExpression = BuildUnSetKeyConstructorExpression(keyType, entityExpression);

            var isKeySetExpresion = Expression.Call(entityExpression, nameof(DummyEntity.GetKeyIsAssigned), new Type[0], new Expression[0]);

            var body = Expression.Condition(
                test: Expression.Equal(isKeySetExpresion, ExpressionEx.Constants.True),
                ifTrue: keySetCtorExpression,
                ifFalse: keyUnSetCtorExpression
                );

            return(Expression.Lambda <Func <object, object> >(ExpressionEx.ConvertIfNeeded(body, typeof(object)), entityParameterExpression).Compile());
        }
Exemplo n.º 11
0
        private Expression BuildEnumPredicate()
        {
            if (DataType != PredicateDataType.Enum)
            {
                return(null);
            }

            var value = NumericTypeHelper.AsNumericFromEnum(Value, EffectiveType, out var comparableType);

            var left = Expression;

            if (IsNullableType)
            {
                left = Expression.Property(left, nameof(Nullable <int> .Value));
            }
            left = ExpressionEx.ConvertIfNeeded(left, comparableType);

            var right = Expression.Constant(value);

            return(BuildEquitableExpression(left, Operator, right)
                   ?? BuildComparableExpression(left, Operator, right));
        }
Exemplo n.º 12
0
        private Expression BuildNumericPredicate()
        {
            if (DataType != PredicateDataType.Number)
            {
                return(null);
            }

            var value = NumericTypeHelper.AsNumeric(Value, EffectiveType, Configuration.NumberStyles, Configuration.FormatProvider, out var comparableType);

            var left = Expression;

            if (numericTypeDescriptor.Nullable)
            {
                left = Expression.Property(Expression, nameof(Nullable <int> .Value));
            }
            left = ExpressionEx.ConvertIfNeeded(left, comparableType);

            var right = Expression.Constant(value);

            return(BuildEquitableExpression(left, Operator, right)
                   ?? BuildComparableExpression(left, Operator, right));
        }
Exemplo n.º 13
0
        internal LambdaExpression BuildGenericInvoker(MethodInfo methodInfo, bool asInstance = false)
        {
            CacheKey cacheKey = null;

            if (EnableCaching)
            {
                cacheKey = new CacheKey(methodInfo, asInstance);
                if (genericCache.TryGetValue(cacheKey, out var cachedLambda))
                {
                    return(cachedLambda);
                }
            }

            var instanceParameter = Expression.Parameter(typeof(object), "instance");
            var inputParameters   = Expression.Parameter(typeof(object[]), "parameters");

            var methodParameters = methodInfo.GetParameters();

            var methodInstanceParameters = methodParameters
                                           .Skip(asInstance && methodInfo.IsExtension() ? 1 : 0)
                                           .ToList();

            var byRefVariables = methodInstanceParameters
                                 .Select((x, i) => new { Index = i, Parameter = x })
                                 .Where(x => x.Parameter.ParameterType.IsByRef)
                                 .Select(x => new
            {
                x.Index,
                Variable = Expression.Variable(x.Parameter.ParameterType.GetElementType(), x.Parameter.Name)
            })
                                 .ToArray();

            var methodCallParameters =
                methodInstanceParameters
                .Select((x, i) => ExpressionEx.ConvertIfNeeded(
                            x.ParameterType.IsByRef ?
                            (Expression)byRefVariables.Single(v => v.Index == i).Variable :
                            (Expression)Expression.ArrayAccess(inputParameters, Expression.Constant(i)),
                            x.ParameterType))
                .ToList();

            Expression invokerExpression;

            ParameterExpression[] expressionParameters;
            Type delegateType;

            //Instance
            if (!methodInfo.IsStatic)
            {
                invokerExpression = Expression.Call(
                    ExpressionEx.ConvertIfNeeded(instanceParameter, methodInfo.DeclaringType),
                    methodInfo,
                    methodCallParameters);

                expressionParameters = new[] { instanceParameter, inputParameters };
                delegateType         = typeof(GenericInstanceInvoker);
            }
            //Extension as Instance
            else if (asInstance && methodInfo.IsExtension())
            {
                invokerExpression = Expression.Call(
                    methodInfo,
                    new Expression[] { ExpressionEx.ConvertIfNeeded(instanceParameter, methodParameters[0].ParameterType) }.Concat(methodCallParameters));

                expressionParameters = new[] { instanceParameter, inputParameters };
                delegateType         = typeof(GenericInstanceInvoker);
            }
            //Static as Instance
            else if (asInstance && methodInfo.IsStatic)
            {
                invokerExpression = Expression.Call(
                    methodInfo,
                    methodCallParameters);

                expressionParameters = new[] { instanceParameter, inputParameters };
                delegateType         = typeof(GenericInstanceInvoker);
            }
            //Static
            else
            {
                invokerExpression = Expression.Call(
                    methodInfo,
                    methodCallParameters);

                expressionParameters = new[] { inputParameters };
                delegateType         = typeof(GenericStaticInvoker);
            }


            var isFunc = methodInfo.ReturnType != typeof(void);



            var byRefAssignmentsFromArray = byRefVariables
                                            .Select(x => (Expression)Expression.Assign(x.Variable,
                                                                                       ExpressionEx.ConvertIfNeeded(
                                                                                           Expression.ArrayAccess(inputParameters, Expression.Constant(x.Index)), x.Variable.Type)));

            var byRefAssignmentsToArray = byRefVariables
                                          .Select(x => (Expression)Expression.Assign(Expression.ArrayAccess(inputParameters, Expression.Constant(x.Index)), ExpressionEx.ConvertIfNeeded(x.Variable, typeof(object))));

            var returnVariable = isFunc && byRefVariables.Any() ? Expression.Variable(methodInfo.ReturnType) : null;

            var declaredVariables =
                (returnVariable != null ? new[] { returnVariable } : Enumerable.Empty <ParameterExpression>())
                .Concat(byRefVariables.Select(x => x.Variable))
                .ToArray();

            var invokerBody = Enumerable.Empty <Expression>()
                              .Concat(byRefAssignmentsFromArray)
                              .Concat(returnVariable != null ? new[] { Expression.Assign(returnVariable, invokerExpression) } : new[] { invokerExpression })
                              .Concat(byRefAssignmentsToArray)
                              .Concat(returnVariable != null ? new[] { returnVariable } : Enumerable.Empty <Expression>());

            if (!isFunc)
            {
                invokerBody = invokerBody.Concat(new Expression[] { Expression.Constant(null) });
            }

            //If is Action, return null as object
            //Else if is Func return actual type and cast to object
            var body = (!isFunc) ?
                       Expression.Block(typeof(object), declaredVariables, invokerBody) :
                       ExpressionEx.ConvertIfNeeded(
                Expression.Block(methodInfo.ReturnType, declaredVariables, invokerBody),
                typeof(object));


            var lambda = Expression.Lambda(delegateType, body, expressionParameters);

            if (EnableCaching)
            {
                genericCache.TryAdd(cacheKey, lambda);
            }

            return(lambda);
        }
Exemplo n.º 14
0
        private LambdaExpression BuildInvokerExpressionFromTypes(MethodInfo methodInfo, Type instanceType, IEnumerable <Type> parameterTypes, Type returnType, Type delegateType)
        {
            if (methodInfo == null)
            {
                throw new ArgumentNullException(nameof(methodInfo));
            }

            CacheKey cacheKey = null;

            if (EnableCaching && delegateType != null)
            {
                cacheKey = new CacheKey(methodInfo, instanceType, returnType, parameterTypes);
                if (byTypesCache.TryGetValue(cacheKey, out var cachedLambda))
                {
                    return(cachedLambda);
                }
            }

            returnType   = returnType ?? methodInfo.ReturnType;
            instanceType = methodInfo.IsStatic ? null : instanceType ?? methodInfo.DeclaringType;

            var methodParameters =
                (methodInfo.IsStatic ?
                 Enumerable.Empty <MethodParameter>() :
                 new[] { new MethodParameter {
                             InputParameter = Expression.Parameter(instanceType, "instance"), MethodType = methodInfo.DeclaringType
                         } })
                .Concat(methodInfo.GetParameters().ZipOutter(parameterTypes ?? Enumerable.Empty <Type>(),
                                                             (mp, pt) => new MethodParameter
            {
                InputParameter = Expression.Parameter(pt ?? mp.ParameterType, mp.Name),
                MethodType     = mp.ParameterType
            }))
                .Select(x => new
            {
                x.InputParameter,
                MethodCallParameter = x.MethodType == x.InputParameter.Type ? (Expression)x.InputParameter : ExpressionEx.ConvertIfNeeded(x.InputParameter, x.MethodType)
            })
                .ToList();

            var isAction = methodInfo.ReturnType == typeof(void) && (returnType == null || returnType == typeof(void));

            var effectiveDelegateType = delegateType ?? (isAction ?
                                                         GenericTypeExtensions.GetActionGenericType(methodParameters.Select(x => x.MethodCallParameter.Type)) :
                                                         GenericTypeExtensions.GetFuncGenericType(methodParameters.Select(x => x.MethodCallParameter.Type).Concat(new[] { returnType }).ToArray()));

            var invokerExpression = Expression.Call(
                methodInfo.IsStatic ? null : methodParameters.Select(x => x.MethodCallParameter).First(),
                methodInfo,
                methodParameters.Select(x => x.MethodCallParameter).Skip(methodInfo.IsStatic ? 0 : 1));

            var body = methodInfo.ReturnType == typeof(void) ?
                       (!isAction ?
                        (Expression)Expression.Block(typeof(object), invokerExpression, Expression.Constant(null)) :
                        invokerExpression) :
                       Expression.Convert(invokerExpression, returnType);

            var lambda = Expression.Lambda(effectiveDelegateType, body, methodParameters.Select(x => x.InputParameter));

            if (EnableCaching && delegateType != null)
            {
                byTypesCache.TryAdd(cacheKey, lambda);
            }

            return(lambda);
        }
        private LambdaExpression BuildFromTypes(ConstructorInfo ctorInfo, Type instanceType, IEnumerable <Type> parameterTypes, Type delegateType)
        {
            CacheKey cacheKey = null;

            if (EnableCaching && delegateType == null)
            {
                cacheKey = new CacheKey(ctorInfo, instanceType, parameterTypes);
                if (cache.TryGetValue(cacheKey, out var lambda))
                {
                    return(lambda);
                }
            }

            var effectiveInstanceType = instanceType ?? ctorInfo.DeclaringType;

            var constructorParameters = ctorInfo.GetParameters()
                                        .ZipOutter(parameterTypes ?? Enumerable.Empty <Type>(),
                                                   (cp, p) => new
            {
                MethodType     = cp.ParameterType,
                Name           = cp.Name,
                InputParameter = Expression.Parameter(p ?? cp.ParameterType, cp.Name),
            })
                                        .Select(x => new
            {
                x.InputParameter,
                MethodCallParameter = x.MethodType == x.InputParameter.Type ? (Expression)x.InputParameter : ExpressionEx.ConvertIfNeeded(x.InputParameter, x.MethodType)
            })
                                        .ToList();

            var effectiveDelegateType = delegateType ?? GenericTypeExtensions.GetFuncGenericType(constructorParameters.Select(x => x.InputParameter.Type).Concat(new[] { effectiveInstanceType }));
            var invokerExpression     = (Expression)Expression.New(ctorInfo, constructorParameters.Select(x => x.MethodCallParameter));

            if (effectiveInstanceType != ctorInfo.DeclaringType)
            {
                invokerExpression = Expression.Convert(invokerExpression, effectiveInstanceType);
            }

            var l = Expression.Lambda(effectiveDelegateType, invokerExpression, constructorParameters.Select(x => x.InputParameter).ToArray());

            if (EnableCaching && delegateType == null)
            {
                cache.TryAdd(cacheKey, l);
            }

            return(l);
        }