private void DoDirectCastWithTypeConstraintDoubleParameter <T>() where T : ITestInterface { var expr = ExpressionUtils.CreateFunctionTerm <T, T, double>(datumConverterFactory, (o1, o2) => ((ITestInterface)o1).SomeNumber); AssertFunctionIsGetFieldSomeNumberDoubleParameter(expr); }
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()); }
protected internal virtual object GetValue(ExpressionState state, Type desiredReturnType) { return(ExpressionUtils.ConvertTypedValue(state.EvaluationContext, GetValueInternal(state), desiredReturnType)); }
public TokenRepository(PostgreSQLTypeLookup typeLookup, PostgreSQLConstants <Token> sqlConstants, EntityUtils entityUtils, ExpressionUtils expressionUtils, PostgreSQLExecutor sqlExecutor) : base(typeLookup, sqlConstants, entityUtils, expressionUtils, sqlExecutor, GetUpdateableFieldsList()) { }
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); }
public void DateTimeAddTicks() { var expr = ExpressionUtils.CreateFunctionTerm <DateTime, DateTime>(datumConverterFactory, dt => dt.AddTicks(1)); AssertAddFunctionWithConversion(expr, 1, 1.0 / TimeSpan.TicksPerSecond); }
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"); } }
private static void RequiresCanRead(Expression expression, string paramName) { ExpressionUtils.RequiresCanRead(expression, paramName); }
public override Expression GetServerEquivalent(Expression controlParameter) => ExpressionUtils.Replace((DotvvmBindableObject c) => new BindingCollectionInfo(c.GetAllAncestors(true, false).OfType <DataItemContainer>().First().DataItemIndex.Value), controlParameter);
/// <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)); }
/// <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)); }
/// <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)); }
public void AddPropertyGetter(string key, Expression <Func <T, object> > expression) { PropertyGetters.Add(key, ExpressionUtils.CompileToObjectTypedFunction(expression)); }
internal override ReadOnlyCollection <Expression> GetOrMakeArguments() { return(ExpressionUtils.ReturnReadOnly(this, ref _arg0)); }
public void DateTimeAddTimeSpan() { var expr = ExpressionUtils.CreateFunctionTerm <DateTime, DateTime>(datumConverterFactory, dt => dt.Add(TimeSpan.FromSeconds(51))); AssertAddFunction(expr, TimeSpan.FromSeconds(51)); }
private static Expression <Func <TestIndexableEntity, object> > GetValidPropertySelectorForTestIndexableEntity(string propertyName) { return(ExpressionUtils.GetPropertySelector <TestIndexableEntity, object>(propertyName)); }
public void DateTimeAddMinutes() { var expr = ExpressionUtils.CreateFunctionTerm <DateTime, DateTime>(datumConverterFactory, dt => dt.AddMinutes(23)); AssertAddFunctionWithConversion(expr, 23, (double)TimeSpan.TicksPerMinute / TimeSpan.TicksPerSecond); }
public override Expression GetServerEquivalent(Expression controlParameter) { return(Expression.Convert(ExpressionUtils.Replace((DotvvmBindableObject c) => c.GetClosestControlBindingTarget(), controlParameter), ResolvedTypeDescriptor.ToSystemType(ParameterType))); }
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(); } }
public override Expression GetServerEquivalent(Expression controlParameter) { return(ExpressionUtils.Replace((DotvvmBindableObject c) => c.GetAllAncestors(true).OfType <DataItemContainer>().First().DataItemIndex.Value, controlParameter)); }
/// <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()); }
internal override bool SameVariables(ICollection <ParameterExpression> variables) => ExpressionUtils.SameElements(variables, _variables);
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); }
internal override ReadOnlyCollection <ParameterExpression> GetOrMakeVariables() { return(ExpressionUtils.ReturnReadOnly(ref _variables)); }
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()); }
internal override bool SameExpressions(ICollection <Expression> expressions) => ExpressionUtils.SameElements(expressions, _body);
/// <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; }
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()); }
public void DirectIntentionalCastToExactSameTypeDoubleParameter() { var expr = ExpressionUtils.CreateFunctionTerm <TestObject, TestObject, double>(datumConverterFactory, (o1, o2) => ((ITestInterface)o1).SomeNumber); AssertFunctionIsGetFieldSomeNumberDoubleParameter(expr); }