Пример #1
0
        private void DoDirectCastWithTypeConstraintDoubleParameter <T>() where T : ITestInterface
        {
            var expr = ExpressionUtils.CreateFunctionTerm <T, T, double>(datumConverterFactory, (o1, o2) => ((ITestInterface)o1).SomeNumber);

            AssertFunctionIsGetFieldSomeNumberDoubleParameter(expr);
        }
Пример #2
0
        this.Properties.Any(p => p.ClientValidationRules.Any());     // it is required for validation

        /// <summary>
        /// Creates the writer factory.
        /// </summary>
        public WriterDelegate CreateWriterFactory()
        {
            var block                 = new List <Expression>();
            var writer                = Expression.Parameter(typeof(JsonWriter), "writer");
            var valueParam            = Expression.Parameter(typeof(object), "valueParam");
            var serializer            = Expression.Parameter(typeof(JsonSerializer), "serializer");
            var encryptedValuesWriter = Expression.Parameter(typeof(EncryptedValuesWriter), "encryptedValuesWriter");
            var isPostback            = Expression.Parameter(typeof(bool), "isPostback");
            var value                 = Expression.Variable(Type, "value");

            // curly brackets are used for variables and methods from the scope of this factory method
            // value = ({Type})valueParam;
            block.Add(Expression.Assign(value, Expression.Convert(valueParam, Type)));

            // writer.WriteStartObject();
            block.Add(Expression.Call(writer, nameof(JsonWriter.WriteStartObject), Type.EmptyTypes));

            // encryptedValuesWriter.Nest();
            block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.Nest), Type.EmptyTypes));

            if (this.RequiredTypeField())
            {
                // writer.WritePropertyName("$type");
                block.Add(ExpressionUtils.Replace((JsonWriter w) => w.WritePropertyName("$type"), writer));

                // serializer.Serialize(writer, value.GetType().FullName)
                block.Add(ExpressionUtils.Replace((JsonSerializer s, JsonWriter w, string t) => w.WriteValue(t), serializer, writer, Expression.Constant(Type.GetTypeHash())));
            }

            // go through all properties that should be serialized
            for (int propertyIndex = 0; propertyIndex < Properties.Count(); propertyIndex++)
            {
                var property         = Properties.ElementAt(propertyIndex);
                var endPropertyLabel = Expression.Label("end_property_" + property.Name);
                var options          = new Dictionary <string, object>();
                if (property.TransferToClient && property.PropertyInfo.GetMethod != null)
                {
                    if (property.TransferFirstRequest != property.TransferAfterPostback)
                    {
                        if (property.ViewModelProtection != ProtectMode.None)
                        {
                            throw new Exception("Property sent only on selected requests can use viewModel protection.");
                        }

                        Expression condition = isPostback;
                        if (property.TransferAfterPostback)
                        {
                            condition = Expression.Not(condition);
                        }

                        block.Add(Expression.IfThen(condition, Expression.Goto(endPropertyLabel)));
                    }

                    // (object)value.{property.PropertyInfo.Name}
                    var prop = Expression.Property(value, property.PropertyInfo);

                    if (property.ViewModelProtection == ProtectMode.EncryptData ||
                        property.ViewModelProtection == ProtectMode.SignData)
                    {
                        // encryptedValuesWriter.Value({propertyIndex}, (object)value.{property.PropertyInfo.Name});
                        block.Add(
                            Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.WriteValue), Type.EmptyTypes, Expression.Constant(propertyIndex), Expression.Convert(prop, typeof(object))));
                    }

                    if (property.ViewModelProtection == ProtectMode.None ||
                        property.ViewModelProtection == ProtectMode.SignData)
                    {
                        var checkEV = CanContainEncryptedValues(property.Type);
                        if (checkEV)
                        {
                            // encryptedValuesWriter.Nest({propertyIndex});
                            block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.Nest), Type.EmptyTypes, Expression.Constant(propertyIndex)));
                        }

                        // writer.WritePropertyName({property.Name});
                        block.Add(Expression.Call(writer, nameof(JsonWriter.WritePropertyName), Type.EmptyTypes,
                                                  Expression.Constant(property.Name)));

                        // serializer.Serialize(serializer, writer, {property}, (object)value.{property.PropertyInfo.Name});
                        block.Add(GetSerializeExpression(property, writer, prop, serializer));

                        if (checkEV)
                        {
                            // encryption is worthless if the property is not being transfered both ways
                            // therefore ClearEmptyNest throws exception if the property contains encrypted values
                            if (!property.IsFullyTransferred())
                            {
                                // encryptedValuesWriter.ClearEmptyNest();
                                block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.ClearEmptyNest), Type.EmptyTypes));
                            }
                            else
                            {
                                // encryptedValuesWriter.End();
                                block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.End), Type.EmptyTypes));
                            }
                        }
                    }

                    if (!property.TransferToServer)
                    {
                        // write an instruction into a viewmodel that the property may not be posted back
                        options["doNotPost"] = true;
                    }
                    else if (property.TransferToServerOnlyInPath)
                    {
                        options["pathOnly"] = true;
                    }
                    if (configuration.ExperimentalFeatures.ServerSideViewModelCache.IsEnabledForAnyRoute() && !property.TransferAfterPostback)
                    {
                        options["firstRequest"] = true;
                    }
                }
                else if (property.TransferToServer)
                {
                    // render empty property options - we need to create the observable on the client, however we don't transfer the value
                    options["doNotUpdate"] = true;
                }

                if (property.ClientExtenders.Any())
                {
                    options[CLIENT_EXTENDERS_KEY] = property.ClientExtenders.ToArray();
                }

                AddTypeOptions(options, property);

                block.Add(Expression.Label(endPropertyLabel));
                if (options.Any())
                {
                    GenerateOptionsBlock(block, property, options, writer);
                }
            }

            // writer.WriteEndObject();
            block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteEndObject(), writer));

            // encryptedValuesWriter.End();
            block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.End), Type.EmptyTypes));

            // compile the expression
            var ex = Expression.Lambda <WriterDelegate>(
                Expression.Block(new[] { value }, block).OptimizeConstants(), writer, valueParam, serializer, encryptedValuesWriter, isPostback);

            return(ex.Compile());
        }
Пример #3
0
 protected internal virtual object GetValue(ExpressionState state, Type desiredReturnType)
 {
     return(ExpressionUtils.ConvertTypedValue(state.EvaluationContext, GetValueInternal(state), desiredReturnType));
 }
Пример #4
0
 public TokenRepository(PostgreSQLTypeLookup typeLookup, PostgreSQLConstants <Token> sqlConstants, EntityUtils entityUtils,
                        ExpressionUtils expressionUtils, PostgreSQLExecutor sqlExecutor) : base(typeLookup, sqlConstants, entityUtils,
                                                                                                expressionUtils, sqlExecutor, GetUpdateableFieldsList())
 {
 }
Пример #5
0
        public bool TryMakeCall(Expression target, ArgumentsTree argumentsTree, BindingContext bindingContext, out Expression expression, out float expressionQuality)
        {
            if (argumentsTree == null)
            {
                throw new ArgumentNullException("argumentsTree");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            if (!this.IsStatic && !this.IsConstructor && target == null)
            {
                throw new ArgumentNullException("target");
            }

            expression        = null;
            expressionQuality = QUALITY_INCOMPATIBLE;

            if (this.member is MethodBase == false)
            {
                return(false);
            }

            // check argument count
            if (argumentsTree.Count > this.parameters.Length)
            {
                return(false);                // not all arguments are bound to parameters
            }
            var requiredParametersCount = this.parameters.Length - this.parameters.Count(p => p.IsOptional);

            if (argumentsTree.Count < requiredParametersCount)
            {
                return(false);                // not all required parameters has values
            }
            // bind arguments
            var parametersQuality = 0.0f;
            var arguments         = default(Expression[]);

            foreach (var argumentName in argumentsTree.Keys)
            {
                var parameter      = default(ParameterInfo);
                var parameterIndex = 0;
                if (HasDigitsOnly(argumentName))
                {
                    parameterIndex = int.Parse(argumentName, Constants.DefaultFormatProvider);
                    if (parameterIndex >= this.parameters.Length)
                    {
                        return(false);                        // position out of range
                    }
                    parameter = this.parameters[parameterIndex];

                    if (argumentsTree.ContainsKey(parameter.Name))
                    {
                        return(false);                        // positional intersects named
                    }
                }
                else
                {
                    if (this.parametersByName.TryGetValue(argumentName, out parameter) == false)
                    {
                        return(false);                        // parameter is not found
                    }
                    parameterIndex = parameter.Position;
                }

                var expectedType = TypeDescription.GetTypeDescription(parameter.ParameterType);
                var argValue     = default(Expression);
                var bindingError = default(Exception);
                if (AnyBinder.TryBindInNewScope(argumentsTree[argumentName], bindingContext, expectedType, out argValue, out bindingError) == false)
                {
                    return(false);
                }

                Debug.Assert(argValue != null, "argValue != null");

                var quality = 0.0f;
                if (ExpressionUtils.TryMorphType(ref argValue, expectedType, out quality) == false || quality <= 0)
                {
                    return(false);                   // failed to bind parameter
                }
                parametersQuality += quality;        // casted
                if (arguments == null)
                {
                    arguments = new Expression[this.parameters.Length];
                }
                arguments[parameterIndex] = argValue;
            }

            if (this.parameters.Length > 0)
            {
                if (arguments == null)
                {
                    arguments = new Expression[this.parameters.Length];
                }
                for (var i = 0; i < arguments.Length; i++)
                {
                    if (arguments[i] != null)
                    {
                        continue;
                    }
                    var parameter = this.parameters[i];
                    if (parameter.IsOptional == false)
                    {
                        return(false);                        // missing required parameter
                    }
                    var typeDescription = TypeDescription.GetTypeDescription(parameter.ParameterType);
                    arguments[i]       = typeDescription.DefaultExpression;
                    parametersQuality += TypeConversion.QUALITY_SAME_TYPE;
                }

                expressionQuality = parametersQuality / this.parameters.Length;
            }
            else
            {
                expressionQuality = QUALITY_EXACT_MATCH;
            }


            if (this.member is MethodInfo)
            {
                if (this.IsStatic)
                {
                    expression = Expression.Call((MethodInfo)this.member, arguments);
                }
                else
                {
                    expression = Expression.Call(target, (MethodInfo)this.member, arguments);
                }
                return(true);
            }
            else if (this.member is ConstructorInfo)
            {
                expression = Expression.New((ConstructorInfo)this.member, arguments);
                return(true);
            }

            expressionQuality = QUALITY_INCOMPATIBLE;
            return(false);
        }
Пример #6
0
        public void DateTimeAddTicks()
        {
            var expr = ExpressionUtils.CreateFunctionTerm <DateTime, DateTime>(datumConverterFactory, dt => dt.AddTicks(1));

            AssertAddFunctionWithConversion(expr, 1, 1.0 / TimeSpan.TicksPerSecond);
        }
Пример #7
0
        private Expression GetControlExpression(int node, Dictionary <int, bool> visited)
        {
            if (visited.ContainsKey(node) && visited[node])
            {
                throw new InvalidGraphException("Infinite flow loop");
            }

            visited[node] = true;

            var currentNode = GetNode(node);

            var inputDataExpressions  = new Expression[currentNode.Inputs.Length];
            var outputFlowExpressions = new Expression[currentNode.Outputs.Length];

            // ASSUMPTION: first input socket is a flow socket, the rest are data sockets
            for (int i = 1; i < currentNode.Inputs.Length; i++)
            {
                var connection = currentNode.Inputs[i][0];
                if (connection == null)
                {
                    inputDataExpressions[i] = GetDefaultValueOfEmptyInput(currentNode.Type, i, currentNode.Data.Value);
                }
                else
                {
                    inputDataExpressions[i] = GetDataExpression(node, i);
                }
            }

            for (int i = 0; i < currentNode.Outputs.Length; i++)
            {
                var connection = currentNode.Outputs[i][0];
                if (connection != null && !FunctionsFacade.IsPureFunction(GetNode(connection.Node).Type))
                {
                    outputFlowExpressions[i] = GetControlExpression(connection.Node, visited);
                }
                else
                {
                    outputFlowExpressions[i] = Expression.Empty();
                }
            }

            visited[node] = false;

            switch (currentNode.Type)
            {
            case FunctionNames.If:
                return(Expression.IfThenElse(
                           Expression.Convert(inputDataExpressions.ElementAtOrDefault(1), typeof(bool)),
                           outputFlowExpressions.ElementAtOrDefault(0),
                           outputFlowExpressions.ElementAtOrDefault(1)
                           ));

            case FunctionNames.ForEach:
                return(Expression.Block(
                           ExpressionUtils.ForEach(
                               inputDataExpressions.ElementAtOrDefault(1),
                               LoopVars[Tuple.Create(node, 1)],
                               outputFlowExpressions.ElementAtOrDefault(0)
                               ),
                           outputFlowExpressions.ElementAtOrDefault(3)
                           ));

            case FunctionNames.For:
                throw new NotImplementedException();

            case FunctionNames.While:
                throw new NotImplementedException();

            case FunctionNames.Return:
                return(Expression.Return(ReturnTarget, inputDataExpressions.ElementAtOrDefault(1)));

            case FunctionNames.Set:
                return(Expression.Block(
                           Expression.Assign(LocalVars[currentNode.Data.Value], inputDataExpressions.ElementAtOrDefault(1)),
                           outputFlowExpressions[0]
                           ));

            default:
                throw new InvalidGraphException("Not a control function or is entry");
            }
        }
Пример #8
0
 private static void RequiresCanRead(Expression expression, string paramName)
 {
     ExpressionUtils.RequiresCanRead(expression, paramName);
 }
Пример #9
0
 public override Expression GetServerEquivalent(Expression controlParameter) =>
 ExpressionUtils.Replace((DotvvmBindableObject c) => new BindingCollectionInfo(c.GetAllAncestors(true, false).OfType <DataItemContainer>().First().DataItemIndex.Value), controlParameter);
Пример #10
0
 /// <summary>
 /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T.
 ///
 /// This is similar to the ReturnReadOnly of T. This version supports nodes which hold
 /// onto multiple Expressions where one is typed to object.  That object field holds either
 /// an expression or a ReadOnlyCollection of Expressions.  When it holds a ReadOnlyCollection
 /// the IList which backs it is a ListArgumentProvider which uses the Expression which
 /// implements IArgumentProvider to get 2nd and additional values.  The ListArgumentProvider
 /// continues to hold onto the 1st expression.
 ///
 /// This enables users to get the ReadOnlyCollection w/o it consuming more memory than if
 /// it was just an array.  Meanwhile The DLR internally avoids accessing  which would force
 /// the readonly collection to be created resulting in a typical memory savings.
 /// </summary>
 internal static ReadOnlyCollection <Expression> ReturnReadOnly(IArgumentProvider provider, ref object collection)
 {
     return(ExpressionUtils.ReturnReadOnly(provider, ref collection));
 }
Пример #11
0
 /// <summary>
 /// Helper which is used for specialized subtypes which use ReturnReadOnly(ref object, ...).
 /// This is the reverse version of ReturnReadOnly which takes an IArgumentProvider.
 ///
 /// This is used to return the 1st argument.  The 1st argument is typed as object and either
 /// contains a ReadOnlyCollection or the Expression.  We check for the Expression and if it's
 /// present we return that, otherwise we return the 1st element of the ReadOnlyCollection.
 /// </summary>
 internal static T ReturnObject <T>(object collectionOrT) where T : class
 {
     return(ExpressionUtils.ReturnObject <T>(collectionOrT));
 }
Пример #12
0
 /// <summary>
 /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T.
 ///
 /// This is called from various methods where we internally hold onto an IList of T
 /// or a readonly collection of T.  We check to see if we've already returned a
 /// readonly collection of T and if so simply return the other one.  Otherwise we do
 /// a thread-safe replacement of the list w/ a readonly collection which wraps it.
 ///
 /// Ultimately this saves us from having to allocate a ReadOnlyCollection for our
 /// data types because the compiler is capable of going directly to the IList of T.
 /// </summary>
 internal static ReadOnlyCollection <T> ReturnReadOnly <T>(ref IList <T> collection)
 {
     return(ExpressionUtils.ReturnReadOnly <T>(ref collection));
 }
Пример #13
0
 public void AddPropertyGetter(string key, Expression <Func <T, object> > expression)
 {
     PropertyGetters.Add(key, ExpressionUtils.CompileToObjectTypedFunction(expression));
 }
Пример #14
0
 internal override ReadOnlyCollection <Expression> GetOrMakeArguments()
 {
     return(ExpressionUtils.ReturnReadOnly(this, ref _arg0));
 }
Пример #15
0
        public void DateTimeAddTimeSpan()
        {
            var expr = ExpressionUtils.CreateFunctionTerm <DateTime, DateTime>(datumConverterFactory, dt => dt.Add(TimeSpan.FromSeconds(51)));

            AssertAddFunction(expr, TimeSpan.FromSeconds(51));
        }
Пример #16
0
 private static Expression <Func <TestIndexableEntity, object> > GetValidPropertySelectorForTestIndexableEntity(string propertyName)
 {
     return(ExpressionUtils.GetPropertySelector <TestIndexableEntity, object>(propertyName));
 }
Пример #17
0
        public void DateTimeAddMinutes()
        {
            var expr = ExpressionUtils.CreateFunctionTerm <DateTime, DateTime>(datumConverterFactory, dt => dt.AddMinutes(23));

            AssertAddFunctionWithConversion(expr, 23, (double)TimeSpan.TicksPerMinute / TimeSpan.TicksPerSecond);
        }
Пример #18
0
 public override Expression GetServerEquivalent(Expression controlParameter)
 {
     return(Expression.Convert(ExpressionUtils.Replace((DotvvmBindableObject c) => c.GetClosestControlBindingTarget(), controlParameter), ResolvedTypeDescriptor.ToSystemType(ParameterType)));
 }
Пример #19
0
        private static void ValidateNewArgs(ConstructorInfo constructor, ref ReadOnlyCollection <Expression> arguments, ref ReadOnlyCollection <MemberInfo> members)
        {
            ParameterInfo[] pis;
            if ((pis = constructor.GetParametersCached()).Length > 0)
            {
                if (arguments.Count != pis.Length)
                {
                    throw Error.IncorrectNumberOfConstructorArguments();
                }
                if (arguments.Count != members.Count)
                {
                    throw Error.IncorrectNumberOfArgumentsForMembers();
                }
                Expression[]? newArguments = null;
                MemberInfo[]? newMembers   = null;
                for (int i = 0, n = arguments.Count; i < n; i++)
                {
                    Expression arg = arguments[i];
                    ExpressionUtils.RequiresCanRead(arg, nameof(arguments), i);
                    MemberInfo member = members[i];
                    ContractUtils.RequiresNotNull(member, nameof(members), i);
                    if (!TypeUtils.AreEquivalent(member.DeclaringType, constructor.DeclaringType))
                    {
                        throw Error.ArgumentMemberNotDeclOnType(member.Name, constructor.DeclaringType !.Name, nameof(members), i);
                    }
                    Type memberType;
                    ValidateAnonymousTypeMember(ref member, out memberType, nameof(members), i);
                    if (!TypeUtils.AreReferenceAssignable(memberType, arg.Type))
                    {
                        if (!TryQuote(memberType, ref arg))
                        {
                            throw Error.ArgumentTypeDoesNotMatchMember(arg.Type, memberType, nameof(arguments), i);
                        }
                    }
                    ParameterInfo pi    = pis[i];
                    Type          pType = pi.ParameterType;
                    if (pType.IsByRef)
                    {
                        pType = pType.GetElementType() !;
                    }
                    if (!TypeUtils.AreReferenceAssignable(pType, arg.Type))
                    {
                        if (!TryQuote(pType, ref arg))
                        {
                            throw Error.ExpressionTypeDoesNotMatchConstructorParameter(arg.Type, pType, nameof(arguments), i);
                        }
                    }
                    if (newArguments == null && arg != arguments[i])
                    {
                        newArguments = new Expression[arguments.Count];
                        for (int j = 0; j < i; j++)
                        {
                            newArguments[j] = arguments[j];
                        }
                    }
                    if (newArguments != null)
                    {
                        newArguments[i] = arg;
                    }

                    if (newMembers == null && member != members[i])
                    {
                        newMembers = new MemberInfo[members.Count];
                        for (int j = 0; j < i; j++)
                        {
                            newMembers[j] = members[j];
                        }
                    }
                    if (newMembers != null)
                    {
                        newMembers[i] = member;
                    }
                }
                if (newArguments != null)
                {
                    arguments = new TrueReadOnlyCollection <Expression>(newArguments);
                }
                if (newMembers != null)
                {
                    members = new TrueReadOnlyCollection <MemberInfo>(newMembers);
                }
            }
            else if (arguments != null && arguments.Count > 0)
            {
                throw Error.IncorrectNumberOfConstructorArguments();
            }
            else if (members != null && members.Count > 0)
            {
                throw Error.IncorrectNumberOfMembersForGivenConstructor();
            }
        }
Пример #20
0
 public override Expression GetServerEquivalent(Expression controlParameter)
 {
     return(ExpressionUtils.Replace((DotvvmBindableObject c) => c.GetAllAncestors(true).OfType <DataItemContainer>().First().DataItemIndex.Value, controlParameter));
 }
Пример #21
0
        /// <summary>
        /// Creates the reader factory.
        /// </summary>
        public Action <JObject, JsonSerializer, object, EncryptedValuesReader> CreateReaderFactory()
        {
            var block                 = new List <Expression>();
            var jobj                  = Expression.Parameter(typeof(JObject), "jobj");
            var serializer            = Expression.Parameter(typeof(JsonSerializer), "serializer");
            var valueParam            = Expression.Parameter(typeof(object), "valueParam");
            var encryptedValuesReader = Expression.Parameter(typeof(EncryptedValuesReader), "encryptedValuesReader");
            var value                 = Expression.Variable(Type, "value");

            // add current object to encrypted values, this is needed because one property can potentionaly contain more objects (is a collection)
            block.Add(Expression.Call(encryptedValuesReader, nameof(EncryptedValuesReader.Nest), Type.EmptyTypes));

            // value = new {Type}();
            block.Add(Expression.Assign(value, Expression.Convert(valueParam, Type)));

            // go through all properties that should be read
            foreach (var property in Properties.Where(p => p.TransferToServer))
            {
                if (property.ViewModelProtection == ProtectMode.EncryptData || property.ViewModelProtection == ProtectMode.SignData)
                {
                    // encryptedValues[(int)jobj["{p.Name}"]]

                    block.Add(Expression.Call(
                                  value,
                                  property.PropertyInfo.SetMethod,
                                  Expression.Convert(
                                      ExpressionUtils.Replace(
                                          (JsonSerializer s, EncryptedValuesReader ev, object existing) => Deserialize(s, ev.ReadValue(), property, existing),
                                          serializer, encryptedValuesReader,
                                          Expression.Convert(Expression.Property(value, property.PropertyInfo), typeof(object))),
                                      property.Type)
                                  ));
                }
                else
                {
                    var checkEV = property.TransferAfterPostback && property.TransferFirstRequest && ShouldCheckEncrypedValues(property.Type);
                    if (checkEV)
                    {
                        // lastEncrypedValuesCount = encrypedValues.Count
                        block.Add(Expression.Call(encryptedValuesReader, nameof(EncryptedValuesReader.Nest), Type.EmptyTypes));
                    }

                    var jsonProp = ExpressionUtils.Replace((JObject j) => j[property.Name], jobj);

                    // if ({jsonProp} != null) value.{p.Name} = deserialize();
                    block.Add(
                        Expression.IfThen(Expression.NotEqual(jsonProp, Expression.Constant(null)),
                                          Expression.Call(
                                              value,
                                              property.PropertyInfo.SetMethod,
                                              Expression.Convert(
                                                  ExpressionUtils.Replace((JsonSerializer s, JObject j, object existingValue) =>
                                                                          Deserialize(s, j[property.Name], property, existingValue),
                                                                          serializer, jobj,
                                                                          property.Populate ?
                                                                          (Expression)Expression.Convert(Expression.Property(value, property.PropertyInfo), typeof(object)) :
                                                                          Expression.Constant(null, typeof(object))),
                                                  property.Type)
                                              )));

                    if (checkEV)
                    {
                        block.Add(Expression.Call(encryptedValuesReader, nameof(EncryptedValuesReader.AssertEnd), Type.EmptyTypes));
                    }
                }
            }

            // close encrypted values
            block.Add(Expression.Call(encryptedValuesReader, nameof(EncryptedValuesReader.AssertEnd), Type.EmptyTypes));

            block.Add(value);


            // build the lambda expression
            var ex = Expression.Lambda <Action <JObject, JsonSerializer, object, EncryptedValuesReader> >(
                Expression.Convert(
                    Expression.Block(Type, new[] { value }, block),
                    typeof(object)).OptimizeConstants(),
                jobj, serializer, valueParam, encryptedValuesReader);

            return(ex.Compile());
        }
Пример #22
0
 internal override bool SameVariables(ICollection <ParameterExpression> variables) =>
 ExpressionUtils.SameElements(variables, _variables);
Пример #23
0
        public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            if (expectedType == null)
            {
                throw new ArgumentNullException("expectedType");
            }

            boundExpression = null;
            bindingError    = null;

            var expressionType = node.GetExpressionType(throwOnError: true);
            var left           = node.GetLeftExpression(throwOnError: true);
            var right          = node.GetRightExpression(throwOnError: true);
            var leftOperand    = default(Expression);
            var rightOperand   = default(Expression);

            if (AnyBinder.TryBindInNewScope(left, bindingContext, TypeDescription.ObjectType, out leftOperand, out bindingError) == false)
            {
                return(false);
            }
            if (AnyBinder.TryBindInNewScope(right, bindingContext, TypeDescription.ObjectType, out rightOperand, out bindingError) == false)
            {
                return(false);
            }

            Debug.Assert(leftOperand != null, "leftOperand != null");
            Debug.Assert(rightOperand != null, "rightOperand != null");

            switch (expressionType)
            {
            case Constants.EXPRESSION_TYPE_ADD:
                if (leftOperand.Type == typeof(string) || rightOperand.Type == typeof(string))
                {
                    boundExpression = Expression.Call
                                      (
                        StringConcat.GetMethodInfo(),
                        Expression.Convert(leftOperand, typeof(object)),
                        Expression.Convert(rightOperand, typeof(object))
                                      );
                    break;
                }
                else
                {
                    if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Add, out boundExpression) == false)
                    {
                        boundExpression = Expression.Add(leftOperand, rightOperand);
                    }
                    break;
                }

            case Constants.EXPRESSION_TYPE_ADD_CHECKED:
                if (leftOperand.Type == typeof(string) || rightOperand.Type == typeof(string))
                {
                    boundExpression = Expression.Call
                                      (
                        StringConcat.GetMethodInfo(),
                        Expression.Convert(leftOperand, typeof(object)),
                        Expression.Convert(rightOperand, typeof(object))
                                      );
                    break;
                }
                else
                {
                    if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.AddChecked, out boundExpression) == false)
                    {
                        boundExpression = Expression.AddChecked(leftOperand, rightOperand);
                    }
                    break;
                }

            case Constants.EXPRESSION_TYPE_SUBTRACT:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Subtract, out boundExpression) == false)
                {
                    boundExpression = Expression.Subtract(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_SUBTRACT_CHECKED:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.SubtractChecked, out boundExpression) == false)
                {
                    boundExpression = Expression.SubtractChecked(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_LEFTSHIFT:
                ExpressionUtils.TryPromoteUnaryOperation(ref leftOperand, ExpressionType.LeftShift, out boundExpression);
                ExpressionUtils.TryPromoteUnaryOperation(ref rightOperand, ExpressionType.LeftShift, out boundExpression);
                boundExpression = Expression.LeftShift(leftOperand, rightOperand);
                break;

            case Constants.EXPRESSION_TYPE_RIGHTSHIFT:
                ExpressionUtils.TryPromoteUnaryOperation(ref leftOperand, ExpressionType.RightShift, out boundExpression);
                ExpressionUtils.TryPromoteUnaryOperation(ref rightOperand, ExpressionType.RightShift, out boundExpression);
                boundExpression = Expression.RightShift(leftOperand, rightOperand);
                break;

            case Constants.EXPRESSION_TYPE_GREATERTHAN:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.GreaterThan, out boundExpression) == false)
                {
                    boundExpression = Expression.GreaterThan(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_GREATERTHAN_OR_EQUAL:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.GreaterThanOrEqual, out boundExpression) == false)
                {
                    boundExpression = Expression.GreaterThanOrEqual(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_LESSTHAN:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.LessThan, out boundExpression) == false)
                {
                    boundExpression = Expression.LessThan(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_LESSTHAN_OR_EQUAL:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.LessThanOrEqual, out boundExpression) == false)
                {
                    boundExpression = Expression.LessThanOrEqual(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_POWER:
                var resultType       = TypeDescription.GetTypeDescription(leftOperand.Type);
                var resultTypeUnwrap = resultType.IsNullable ? resultType.UnderlyingType : resultType;
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Power, out boundExpression) == false)
                {
                    var operandsType      = TypeDescription.GetTypeDescription(leftOperand.Type);
                    var operandTypeUnwrap = operandsType.IsNullable ? operandsType.UnderlyingType : operandsType;
                    var promoteToNullable = resultType.IsNullable || operandsType.IsNullable;
                    if (operandTypeUnwrap != typeof(double) && leftOperand.Type == rightOperand.Type)
                    {
                        leftOperand  = Expression.ConvertChecked(leftOperand, promoteToNullable ? typeof(double?) : typeof(double));
                        rightOperand = Expression.ConvertChecked(rightOperand, promoteToNullable ? typeof(double?) : typeof(double));
                    }
                    boundExpression = Expression.Power(leftOperand, rightOperand);

                    if (resultType != typeof(double))
                    {
                        boundExpression = Expression.ConvertChecked(boundExpression, promoteToNullable ? resultTypeUnwrap.GetNullableType() : resultTypeUnwrap);
                    }
                }
                break;

            case Constants.EXPRESSION_TYPE_DIVIDE:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Divide, out boundExpression) == false)
                {
                    boundExpression = Expression.Divide(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_MULTIPLY:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Multiply, out boundExpression) == false)
                {
                    boundExpression = Expression.Multiply(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_MULTIPLY_CHECKED:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.MultiplyChecked, out boundExpression) == false)
                {
                    boundExpression = Expression.MultiplyChecked(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_MODULO:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Modulo, out boundExpression) == false)
                {
                    boundExpression = Expression.Modulo(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_EQUAL:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Equal, out boundExpression) == false)
                {
                    boundExpression = Expression.Equal(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_NOTEQUAL:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.NotEqual, out boundExpression) == false)
                {
                    boundExpression = Expression.NotEqual(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_AND:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.And, out boundExpression) == false)
                {
                    boundExpression = Expression.And(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_OR:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Or, out boundExpression) == false)
                {
                    boundExpression = Expression.Or(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_EXCLUSIVEOR:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.ExclusiveOr, out boundExpression) == false)
                {
                    boundExpression = Expression.ExclusiveOr(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_ANDALSO:
                boundExpression = Expression.AndAlso(leftOperand, rightOperand);
                break;

            case Constants.EXPRESSION_TYPE_ORELSE:
                boundExpression = Expression.OrElse(leftOperand, rightOperand);
                break;

            case Constants.EXPRESSION_TYPE_COALESCE:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Coalesce, out boundExpression) == false)
                {
                    boundExpression = Expression.Coalesce(leftOperand, rightOperand);
                }

                break;

            default:
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType), node);
                return(false);
            }
            return(true);
        }
Пример #24
0
 internal override ReadOnlyCollection <ParameterExpression> GetOrMakeVariables()
 {
     return(ExpressionUtils.ReturnReadOnly(ref _variables));
 }
Пример #25
0
        public string ToString([NotNull] IRow row,
                               bool constraintOnly,
                               [CanBeNull] ICollection <string> addedConstraintFieldNames)
        {
            DataView dataView = ConstraintView;

            if (dataView == null)
            {
                return(string.Empty);
            }

            var sb = new StringBuilder();

            CreateDataRow(row, ColumnInfos);
            DataTable dataTable = dataView.Table;

            if (constraintOnly)
            {
                foreach (string fieldNameCandidate in
                         ExpressionUtils.GetExpressionTokens(dataView.RowFilter))
                {
                    int columnIndex = dataTable.Columns.IndexOf(fieldNameCandidate);

                    if (columnIndex < 0 || columnIndex >= ColumnInfos.Count)
                    {
                        continue;
                    }

                    // the candidate matches an existing column

                    if (addedConstraintFieldNames != null)
                    {
                        if (addedConstraintFieldNames.Contains(fieldNameCandidate))
                        {
                            continue;
                        }

                        addedConstraintFieldNames.Add(fieldNameCandidate);
                    }

                    if (sb.Length > 0)
                    {
                        sb.Append("; ");
                    }

                    ColumnInfo columnInfo = GetColumnInfo(columnIndex);
                    sb.AppendFormat("{0} = {1}",
                                    GetDataTableColumnName(columnIndex),
                                    columnInfo.FormatValue(row));
                }
            }
            else
            {
                var columnIndex = 0;
                foreach (ColumnInfo columnInfo in ColumnInfos)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append("; ");
                    }

                    sb.AppendFormat("{0} = {1}",
                                    GetDataTableColumnName(columnIndex),
                                    columnInfo.FormatValue(row));
                    columnIndex++;
                }
            }

            return(sb.ToString());
        }
Пример #26
0
 internal override bool SameExpressions(ICollection <Expression> expressions) =>
 ExpressionUtils.SameElements(expressions, _body);
Пример #27
0
        /// <summary>
        /// Creates the reader factory.
        /// </summary>
        public ReaderDelegate CreateReaderFactory()
        {
            var block                 = new List <Expression>();
            var reader                = Expression.Parameter(typeof(JsonReader), "reader");
            var serializer            = Expression.Parameter(typeof(JsonSerializer), "serializer");
            var valueParam            = Expression.Parameter(typeof(object), "valueParam");
            var encryptedValuesReader = Expression.Parameter(typeof(EncryptedValuesReader), "encryptedValuesReader");
            var value                 = Expression.Variable(Type, "value");
            var currentProperty       = Expression.Variable(typeof(string), "currentProperty");

            // add current object to encrypted values, this is needed because one property can potentially contain more objects (is a collection)
            block.Add(Expression.Call(encryptedValuesReader, nameof(EncryptedValuesReader.Nest), Type.EmptyTypes));

            // curly brackets are used for variables and methods from the context of this factory method
            // value = ({Type})valueParam;
            block.Add(Expression.Assign(value, Expression.Convert(valueParam, Type)));

            // if the reader is in an invalid state, throw an exception
            // TODO: Change exception type, just Exception is not exactly descriptive
            block.Add(ExpressionUtils.Replace((JsonReader rdr) => rdr.TokenType == JsonToken.StartObject ? rdr.Read() : ExpressionUtils.Stub.Throw <bool>(new Exception($"TokenType = StartObject was expected.")), reader));

            var propertiesSwitch = new List <SwitchCase>();

            // iterate through all properties even if they're gonna get skipped
            // it's important for the index to count with all the properties that viewModel contains because the client will send some of them only sometimes
            for (int propertyIndex = 0; propertyIndex < Properties.Count(); propertyIndex++)
            {
                var property = Properties.ElementAt(propertyIndex);
                if (!property.TransferToServer || property.PropertyInfo.SetMethod == null)
                {
                    continue;
                }

                if (property.ViewModelProtection == ProtectMode.EncryptData || property.ViewModelProtection == ProtectMode.SignData)
                {
                    // value.{property} = ({property.Type})Deserialize(serializer, encryptedValuesReader.ReadValue({propertyIndex}), {property}, (object)value.{PropertyInfo});
                    block.Add(Expression.Call(
                                  value,
                                  property.PropertyInfo.SetMethod,
                                  Expression.Convert(
                                      ExpressionUtils.Replace(
                                          (JsonSerializer s, EncryptedValuesReader ev, object existing) => Deserialize(s, ev.ReadValue(propertyIndex).CreateReader(), property, existing),
                                          serializer, encryptedValuesReader,
                                          Expression.Convert(Expression.Property(value, property.PropertyInfo), typeof(object))),
                                      property.Type)
                                  ).OptimizeConstants());
                }
                else
                {
                    // propertyBlock is the body of this currentProperty's switch case
                    var propertyblock = new List <Expression>();
                    var checkEV       = CanContainEncryptedValues(property.Type);
                    if (checkEV)
                    {
                        // encryptedValuesReader.Nest({propertyIndex});
                        propertyblock.Add(Expression.Call(encryptedValuesReader, nameof(EncryptedValuesReader.Nest), Type.EmptyTypes, Expression.Constant(propertyIndex)));
                    }

                    // existing value is either null or the value {property} depending on property.Populate
                    // value.{property} = ({property.Type})Deserialize(serializer, reader, existing value);
                    propertyblock.Add(
                        Expression.Call(
                            value,
                            property.PropertyInfo.SetMethod,
                            Expression.Convert(
                                ExpressionUtils.Replace((JsonSerializer s, JsonReader j, object existingValue) =>
                                                        Deserialize(s, j, property, existingValue),
                                                        serializer, reader,
                                                        property.Populate ?
                                                        (Expression)Expression.Convert(Expression.Property(value, property.PropertyInfo), typeof(object)) :
                                                        Expression.Constant(null, typeof(object))),
                                property.Type)
                            ));

                    // reader.Read();
                    propertyblock.Add(
                        Expression.Call(reader, "Read", Type.EmptyTypes));

                    if (checkEV)
                    {
                        // encryptedValuesReader.AssertEnd();
                        propertyblock.Add(Expression.Call(encryptedValuesReader, nameof(EncryptedValuesReader.AssertEnd), Type.EmptyTypes));
                    }

                    // create this currentProperty's switch case
                    // case {property.Name}:
                    //     {propertyBlock}
                    propertiesSwitch.Add(Expression.SwitchCase(
                                             Expression.Block(typeof(void), propertyblock),
                                             Expression.Constant(property.Name)
                                             ));
                }
            }

            // WARNING: the following code is not commented out. It's a transcription of the expression below it. Yes, it's long.
            // while(reader reads properties and assigns them to currentProperty)
            // {
            //     switch(currentProperty)
            //     {
            //     {propertiesSwitch}
            //     default:
            //         if(reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.Start)
            //         {
            //             reader.Skip();
            //         }
            //         reader.Read();
            //     }
            // }
            block.Add(ExpressionUtils.While(
                          ExpressionUtils.Replace((JsonReader rdr, string val) => rdr.TokenType == JsonToken.PropertyName &&
                                                  ExpressionUtils.Stub.Assign(val, rdr.Value as string) != null &&
                                                  rdr.Read(), reader, currentProperty),
                          ExpressionUtils.Switch(currentProperty,
                                                 Expression.Block(typeof(void),
                                                                  Expression.IfThen(
                                                                      ExpressionUtils.Replace((JsonReader rdr) => rdr.TokenType == JsonToken.StartArray || rdr.TokenType == JsonToken.StartConstructor || rdr.TokenType == JsonToken.StartObject, reader),
                                                                      Expression.Call(reader, "Skip", Type.EmptyTypes)),
                                                                  Expression.Call(reader, "Read", Type.EmptyTypes)),
                                                 propertiesSwitch.ToArray())
                          ));

            // close encrypted values
            // encryptedValuesReader.AssertEnd();
            block.Add(Expression.Call(encryptedValuesReader, nameof(EncryptedValuesReader.AssertEnd), Type.EmptyTypes));

            //TODO: find out why this is here
            block.Add(value);

            // build the lambda expression
            var ex = Expression.Lambda <ReaderDelegate>(
                Expression.Convert(
                    Expression.Block(Type, new[] { value, currentProperty }, block),
                    typeof(object)).OptimizeConstants(),
                reader, serializer, valueParam, encryptedValuesReader);

            return(ex.Compile());
            //return null;
        }
Пример #28
0
 internal override ReadOnlyCollection <Expression> GetOrMakeExpressions()
 {
     return(ExpressionUtils.ReturnReadOnly(ref _body));
 }
        /// <summary>
        /// Creates the writer factory.
        /// </summary>
        public Action <JsonWriter, object, JsonSerializer, EncryptedValuesWriter, bool> CreateWriterFactory()
        {
            var block                 = new List <Expression>();
            var writer                = Expression.Parameter(typeof(JsonWriter), "writer");
            var valueParam            = Expression.Parameter(typeof(object), "valueParam");
            var serializer            = Expression.Parameter(typeof(JsonSerializer), "serializer");
            var encryptedValuesWriter = Expression.Parameter(typeof(EncryptedValuesWriter), "encryptedValuesWriter");
            var isPostback            = Expression.Parameter(typeof(bool), "isPostback");
            var value                 = Expression.Variable(Type, "value");

            // value = ({Type})valueParam;
            block.Add(Expression.Assign(value, Expression.Convert(valueParam, Type)));
            block.Add(Expression.Call(writer, "WriteStartObject", Type.EmptyTypes));

            block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.Nest), Type.EmptyTypes));

            // writer.WritePropertyName("$validationErrors")
            // writer.WriteStartArray()
            // writer.WriteEndArray()
            block.Add(ExpressionUtils.Replace((JsonWriter w) => w.WritePropertyName("$validationErrors"), writer));
            block.Add(ExpressionUtils.Replace((JsonWriter w) => w.WriteStartArray(), writer));
            block.Add(ExpressionUtils.Replace((JsonWriter w) => w.WriteEndArray(), writer));

            // writer.WritePropertyName("$type");
            // serializer.Serialize(writer, value.GetType().FullName)
            block.Add(ExpressionUtils.Replace((JsonWriter w) => w.WritePropertyName("$type"), writer));
            block.Add(ExpressionUtils.Replace((JsonSerializer s, JsonWriter w, string t) => s.Serialize(w, t), serializer, writer, Expression.Constant(Type.FullName)));

            // go through all properties that should be serialized
            foreach (var property in Properties)
            {
                var endPropertyLabel = Expression.Label("end_property_" + property.Name);
                var options          = new Dictionary <string, object>();
                if (property.TransferToClient)
                {
                    if (property.TransferFirstRequest != property.TransferAfterPostback)
                    {
                        if (property.ViewModelProtection != ViewModelProtectionSettings.None)
                        {
                            throw new Exception("Property sent only on selected requests can use viewModel protection.");
                        }

                        Expression condition = isPostback;
                        if (property.TransferAfterPostback)
                        {
                            condition = Expression.Not(condition);
                        }
                        block.Add(Expression.IfThen(condition, Expression.Goto(endPropertyLabel)));
                    }

                    // writer.WritePropertyName("{property.Name"});
                    var prop = Expression.Convert(Expression.Property(value, property.PropertyInfo), typeof(object));

                    if (property.ViewModelProtection == ViewModelProtectionSettings.EnryptData ||
                        property.ViewModelProtection == ViewModelProtectionSettings.SignData)
                    {
                        // encryptedValues.Add(JsonConvert.SerializeObject({value}));
                        block.Add(
                            Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.Value), Type.EmptyTypes, prop));
                    }

                    if (property.ViewModelProtection == ViewModelProtectionSettings.None ||
                        property.ViewModelProtection == ViewModelProtectionSettings.SignData)
                    {
                        var checkEV = property.ViewModelProtection == ViewModelProtectionSettings.None &&
                                      ShouldCheckEncrypedValues(property.Type);
                        if (checkEV)
                        {
                            // lastEncrypedValuesCount = encrypedValues.Count
                            block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.Nest), Type.EmptyTypes));
                        }

                        block.Add(Expression.Call(writer, "WritePropertyName", Type.EmptyTypes,
                                                  Expression.Constant(property.Name)));

                        // serializer.Serialize(writer, value.{property.Name});
                        block.Add(ExpressionUtils.Replace((JsonSerializer s, JsonWriter w, object v) => Serialize(s, w, property, v), serializer, writer, prop));

                        if (checkEV)
                        {
                            // if not fully transported, ensure nothing happened
                            if (property.TransferAfterPostback != property.TransferFirstRequest && !property.TransferToServer)
                            {
                                block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.ClearEmptyNest), Type.EmptyTypes));
                            }
                            else
                            {
                                block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.End), Type.EmptyTypes));
                            }
                        }
                    }

                    if (!property.TransferToServer)
                    {
                        // write an instruction into a viewmodel that the property may not be posted back
                        options["doNotPost"] = true;
                    }
                    else if (property.TransferToServerOnlyInPath)
                    {
                        options["pathOnly"] = true;
                    }
                }
                else if (property.TransferToServer)
                {
                    // render empty property options - we need to create the observable on the client, however we don't transfer the value
                    options["doNotUpdate"] = true;
                }

                if ((property.Type == typeof(DateTime) || property.Type == typeof(DateTime?)) && property.JsonConverter == null)      // TODO: allow customization using attributes
                {
                    options["isDate"] = true;
                }

                block.Add(Expression.Label(endPropertyLabel));
                if (options.Any())
                {
                    block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WritePropertyName(property.Name + "$options"), writer));
                    block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteStartObject(), writer));
                    foreach (var option in options)
                    {
                        block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WritePropertyName(option.Key), writer));
                        block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteValue(option.Value), writer));
                    }
                    block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteEndObject(), writer));
                }
            }

            block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteEndObject(), writer));
            block.Add(Expression.Call(encryptedValuesWriter, nameof(EncryptedValuesWriter.End), Type.EmptyTypes));
            // compile the expression
            var ex = Expression.Lambda <Action <JsonWriter, object, JsonSerializer, EncryptedValuesWriter, bool> >(
                Expression.Block(new[] { value }, block).OptimizeConstants(), writer, valueParam, serializer, encryptedValuesWriter, isPostback);

            return(ex.Compile());
        }
Пример #30
0
        public void DirectIntentionalCastToExactSameTypeDoubleParameter()
        {
            var expr = ExpressionUtils.CreateFunctionTerm <TestObject, TestObject, double>(datumConverterFactory, (o1, o2) => ((ITestInterface)o1).SomeNumber);

            AssertFunctionIsGetFieldSomeNumberDoubleParameter(expr);
        }