private static IEqualityComparer <T> KeyValuePairEqualityComparer <T>(Type type) { var l = Expression.Parameter(type, "l"); var r = Expression.Parameter(type, "r"); var keyL = Expression.Property(l, "Key"); var keyR = Expression.Property(r, "Key"); var valueL = Expression.Property(l, "Value"); var valueR = Expression.Property(r, "Value"); var keyComparer = ExistingEqualityComparer(keyL.Type); var valueComparer = ExistingEqualityComparer(valueL.Type); var keysEqual = Expression.Call(keyComparer.Item1, keyComparer.Item2, keyL, keyR); var valuesEqual = Expression.Call(valueComparer.Item1, valueComparer.Item2, valueL, valueR); var equals = Expression.And(keysEqual, valuesEqual); var hashCodeKey = Expression.Call(keyComparer.Item1, keyComparer.Item3, keyL); var hashCodeValue = Expression.Call(valueComparer.Item1, valueComparer.Item3, valueL); var hashCode = HashCodeSeed(); var hashCodeStepMultiplier = HashCodeStepMultiplier(); hashCode = BinaryExpression.Add(hashCodeKey, BinaryExpression.Multiply(hashCode, hashCodeStepMultiplier)); hashCode = BinaryExpression.Add(hashCodeValue, BinaryExpression.Multiply(hashCode, hashCodeStepMultiplier)); return(new FuncEqualityComparer <T>( Expression.Lambda <DelegateFunc <T, T, bool> >(equals, l, r).Compile(), Expression.Lambda <DelegateFunc <T, int> >(hashCode, l).Compile())); }
public static Expression DefaultMergeFunction <T>() where T : struct, IComparable { ParameterExpression val1Expr = Expression.Parameter(typeof(T), "oldvalue"); ParameterExpression val2Expr = Expression.Parameter(typeof(T), "newvalue"); BinaryExpression addExpr = BinaryExpression.Add(val1Expr, val2Expr); var lambdaExpr = Expression.Lambda <Func <T, T, T> >( addExpr, new ParameterExpression[] { val1Expr, val2Expr }); return(lambdaExpr); }
static void Main(string[] args) { Console.WriteLine("Start TestLinqExpression"); Func <int> f1 = () => 2 + 2; int res = f1(); Console.WriteLine(res); // Теперь повторим это через Expression (заменим слагаемые) Expression exp = BinaryExpression.Add(ConstantExpression.Constant(4), ConstantExpression.Constant(4)); var f2 = Expression.Lambda <Func <int> >(exp).Compile(); res = f2(); Console.WriteLine(res); // Теперь придумываем "язык" для формул exp. Язык будет объектным. Константа c целого типа будет // соответствовать выражению ConstantExpression.Constant(c), массив object[] {"Add", object1, object2} // будет BinaryExpression.Add(object1, object2) // Делаем транслятор object -> Expression Func <object, Expression> objectTranslator = null; objectTranslator = (object ob) => { if (ob is int) { return(ConstantExpression.Constant(ob)); } return(null); }; // испытываем Expression expr2 = objectTranslator(444); Console.WriteLine(Expression.Lambda <Func <int> >(expr2).Compile()()); // Делаем другую ветвь в трансляторе objectTranslator = (object ob) => { if (ob is int) { return(ConstantExpression.Constant(ob)); } if (ob is object[]) { object[] arr = (object[])ob; if ((string)arr[0] == "Add") { return(BinaryExpression.Add(objectTranslator(arr[1]), objectTranslator(arr[1]))); } } return(null); }; // испытываем object[] myexpression = new object[] { "Add", 2222, 4444 }; // Вот он язык описания вычислений!!! Expression expr3 = objectTranslator(myexpression); Console.WriteLine(Expression.Lambda <Func <int> >(expr3).Compile()()); myexpression = new object[] { "Add", new object[] { "Add", 2, 2 }, new object[] { "Add", 2, 2 } }; Console.WriteLine(Expression.Lambda <Func <int> >(objectTranslator(myexpression)).Compile()()); }
private static Expression GenerateStringConcat(Expression left, Expression right) { return(BinaryExpression.Add(left, right, typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }))); }