public void AccessibleTypesCanBeSpecifiedOnEachCall() { DynamicExpression .ParseLambda(typeof(int), typeof(bool), "it != null"); DynamicExpression. ParseLambda(typeof(int), typeof(bool), "it == Int32(MyEnum.Yes)", additionalAllowedTypes: new[] { typeof(MyEnum) }); }
public void AccessEnumInExpressionWorks() { var expression = "it == Int32(MyEnum.Yes)"; var expr = (Expression <Func <int, bool> >)DynamicExpression .ParseLambda(typeof(int), typeof(bool), expression, additionalAllowedTypes: new[] { typeof(MyEnum) }); expr.ShouldNotBeNull(); var func = expr.Compile(); func((int)MyEnum.Yes).ShouldBeTrue(); func((int)MyEnum.No).ShouldBeFalse(); }
public void EnumWithoutCastIsConvertedFromInt32ToInt64() { var expression = "it == MyEnum.Yes"; var expr = (Expression <Func <long, bool> >)DynamicExpression .ParseLambda(typeof(long), typeof(bool), expression, additionalAllowedTypes: new[] { typeof(MyEnum) }); expr.ShouldNotBeNull(); var func = expr.Compile(); func((int)MyEnum.Yes).ShouldBeTrue(); func((int)MyEnum.No).ShouldBeFalse(); }
public void ParseSimpleExpressionWorks() { var expression = @"x.Length == 4"; var expr = (Expression <Func <string, bool> >)DynamicExpression .ParseLambda(new[] { Expression.Parameter(typeof(string), "x") }, typeof(bool), expression); Assert.NotNull(expr); var values = new[] { "bar", "dog", "food", "water" }.AsQueryable(); var results = values.Where(expr).ToList(); results.Count.ShouldBe(1); results[0].ShouldBe("food"); }
public void EnumWithoutCastIsConvertedToDestinationType() { var expression = "it == MyEnum.Yes"; var expr = (Expression <Func <int, bool> >)DynamicExpression .ParseLambda(typeof(int), typeof(bool), expression, additionalAllowedTypes: new[] { typeof(MyEnum) }); output.WriteLine("{0}", expr); expr.ShouldNotBeNull(); var func = expr.Compile(); func((int)MyEnum.Yes).ShouldBeTrue(); func((int)MyEnum.No).ShouldBeFalse(); }
public void CanParseFirstOrDefaultExpressionWithoutParams(object[] a, object expectedesult) { var expression = "FirstOrDefault()"; var expr = (Expression <Func <IEnumerable <object>, object> >)DynamicExpression .ParseLambda(typeof(IEnumerable <object>), typeof(object), expression); output.WriteLine("{0}", expr); expr.ShouldNotBeNull(); var func = expr.Compile(); var result = func(a); result.ShouldBe(expectedesult); }
public void CanParseFirstOrDefaultExpression() { var expression = "FirstOrDefault(it == \"2\")"; var expr = (Expression <Func <IEnumerable <string>, string> >)DynamicExpression .ParseLambda(typeof(IEnumerable <string>), typeof(string), expression); output.WriteLine("{0}", expr); Assert.NotNull(expr); var func = expr.Compile(); func(new[] { "1", "2", "3" }).ShouldBe("2"); func(new[] { "4" }).ShouldBeNull(); }
public void ParseSubQueryExpressionWorks() { var expression = "x.Any(it == 'a')"; var expr = (Expression <Func <IEnumerable <char>, bool> >)DynamicExpression .ParseLambda(new[] { Expression.Parameter(typeof(IEnumerable <char>), "x") }, typeof(bool), expression); Assert.NotNull(expr); var values = new[] { "bar", "dog", "food", "water" }.AsQueryable(); var results = values.Where(expr).ToList(); results.Count.ShouldBe(2); results[0].ShouldBe("bar"); results[1].ShouldBe("water"); }
public void CanParseNew() { var expression = "new(resource.Length alias Len)"; var parameters = new[] { Expression.Parameter(typeof(string), "resource"), }; var expr = (Expression <Func <string, object> >)DynamicExpression .ParseLambda(parameters, typeof(object), expression); Console.WriteLine(expr); Assert.NotNull(expr); var func = expr.Compile(); }
/// <summary> /// Correlates the elements of two sequences based on matching keys. /// </summary> /// <param name="outer">The first sequence to join.</param> /// <param name="inner">The sequence to join to the first sequence.</param> /// <param name="outerKeySelector">A dynamic function to extract the join key from each element of the first sequence.</param> /// <param name="innerKeySelector">A dynamic function to extract the join key from each element of the second sequence.</param> /// <param name="resultSelector">A dynamic function to create a result element from two matching elements.</param> /// <param name="args">An object array that contains zero or more objects to insert into the predicates as parameters. Similar to the way String.Format formats strings.</param> /// <returns>An <see cref="IQueryable"/> obtained by performing an inner join on two sequences.</returns> public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerKeySelector, string innerKeySelector, string resultSelector, params object[] args) { //http://stackoverflow.com/questions/389094/how-to-create-a-dynamic-linq-join-extension-method if (outer == null) { throw new ArgumentNullException(nameof(outer)); } if (inner == null) { throw new ArgumentNullException(nameof(inner)); } if (string.IsNullOrEmpty(outerKeySelector)) { throw new ArgumentNullException(nameof(outerKeySelector)); } if (string.IsNullOrEmpty(innerKeySelector)) { throw new ArgumentNullException(nameof(innerKeySelector)); } if (string.IsNullOrEmpty(resultSelector)) { throw new ArgumentNullException(nameof(resultSelector)); } LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(outer.ElementType, null, outerKeySelector, args); LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, null, innerKeySelector, args); ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(inner.AsQueryable().ElementType, "inner") }; LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, resultSelector, args); return(outer.Provider.CreateQuery( Expression.Call( typeof(Queryable), "Join", new Type[] { outer.ElementType, inner.AsQueryable().ElementType, outerSelectorLambda.Body.Type, resultsSelectorLambda.Body.Type }, outer.Expression, inner.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda)))); }
/// <summary> /// Groups the elements of a sequence according to a specified key string function /// and creates a result value from each group and its key. /// </summary> /// <param name="source">A <see cref="IQueryable"/> whose elements to group.</param> /// <param name="keySelector">A string expression to specify the key for each element.</param> /// <param name="resultSelector">A string expression to specify a result value from each group.</param> /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param> /// <returns>A <see cref="IQueryable"/> where each element represents a projection over a group and its key.</returns> /// <example> /// <code> /// var groupResult1 = qry.GroupBy("NumberPropertyAsKey", "StringProperty"); /// var groupResult2 = qry.GroupBy("new (NumberPropertyAsKey, StringPropertyAsKey)", "new (StringProperty1, StringProperty2)"); /// </code> /// </example> public static IQueryable GroupBy(this IQueryable source, string keySelector, string resultSelector, object[] args) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (resultSelector == null) { throw new ArgumentNullException(nameof(resultSelector)); } #if NET35 if (string.IsNullOrEmpty(keySelector) || keySelector.All(c => Char.IsWhiteSpace(c))) #else if (string.IsNullOrWhiteSpace(keySelector)) #endif { throw new ArgumentException("Expected non-empty string", nameof(keySelector)); } #if NET35 if (string.IsNullOrEmpty(resultSelector) || resultSelector.All(c => Char.IsWhiteSpace(c))) #else if (string.IsNullOrWhiteSpace(resultSelector)) #endif { throw new ArgumentException("Expected non-empty string", nameof(resultSelector)); } LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, args); LambdaExpression elementLambda = DynamicExpression.ParseLambda(source.ElementType, null, resultSelector, args); return(source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "GroupBy", new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type }, source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)))); }
public static IQueryable Select(this IQueryable source, string selector, params object[] values) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (selector == null) { throw new ArgumentNullException(nameof(selector)); } var lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, values); return(source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "Select", new Type[] { source.ElementType, lambda.Body.Type }, source.Expression, Expression.Quote(lambda)))); }
public void CanParseIsUsingBuiltInType() { var expression = "resource is Double"; var parameters = new[] { Expression.Parameter(typeof(object), "resource"), }; var expr = (Expression <Func <object, bool> >)DynamicExpression .ParseLambda(parameters, typeof(bool), expression); Console.WriteLine(expr); Assert.NotNull(expr); var func = expr.Compile(); Assert.True(func(2.2)); }
public void CanParseAs() { var expression = "(resource as System.String).Length"; var parameters = new[] { Expression.Parameter(typeof(object), "resource"), }; var expr = (Expression <Func <object, int> >)DynamicExpression .ParseLambda(parameters, typeof(int), expression); Console.WriteLine(expr); Assert.NotNull(expr); var func = expr.Compile(); Assert.Equal(5, func("hello")); }
public static IQueryable Where(this IQueryable source, string predicate, params object[] values) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } var lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values); return(source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "Where", new Type[] { source.ElementType }, source.Expression, Expression.Quote(lambda)))); }
public static IQueryable GroupBy(this IQueryable source, string keySelector, string elementSelector, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (elementSelector == null) { throw new ArgumentNullException("elementSelector"); } LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values); LambdaExpression elementLambda = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, values); return(source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "GroupBy", new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type }, source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)))); }
public void CanParseIs() { var expression = "resource is System.String"; var parameters = new[] { Expression.Parameter(typeof(object), "resource"), }; var expr = (Expression <Func <object, bool> >)DynamicExpression .ParseLambda(parameters, typeof(bool), expression); Console.WriteLine(expr); Assert.NotNull(expr); var func = expr.Compile(); Assert.True(func("hello")); Assert.False(func(2)); }
/// <summary> /// Groups the elements of a sequence according to multiple specified key string functions /// and creates a result value from each group (and subgroups) and its key. /// </summary> /// <typeparam name="TElement"></typeparam> /// <param name="source">A <see cref="IEnumerable{T}"/> whose elements to group.</param> /// <param name="keySelectors"><see cref="string"/> expressions to specify the keys for each element.</param> /// <returns>A <see cref="IEnumerable{T}"/> of type <see cref="GroupResult"/> where each element represents a projection over a group, its key, and its subgroups.</returns> public static IEnumerable <GroupResult> GroupByMany <TElement>(this IEnumerable <TElement> source, params string[] keySelectors) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (keySelectors == null) { throw new ArgumentNullException(nameof(keySelectors)); } var selectors = new List <Func <TElement, object> >(keySelectors.Length); foreach (var selector in keySelectors) { LambdaExpression l = DynamicExpression.ParseLambda(typeof(TElement), typeof(object), selector); selectors.Add((Func <TElement, object>)l.Compile()); } return(GroupByManyInternal(source, selectors.ToArray(), 0)); }
public static Func <T, T, int> CreateComparer <T>(string propertyName, bool ascending) { string expression; if (ascending) { expression = string.Format("(item1.{0} == item2.{0}) ? 0 : (item1.{0} > item2.{0}) ? 1 : -1", propertyName); } else { expression = string.Format("(item2.{0} == item1.{0}) ? 0 : (item2.{0} > item1.{0}) ? 1 : -1", propertyName); } ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(typeof(T), "item1"), Expression.Parameter(typeof(T), "item2") }; LambdaExpression lambdaExpression = DynamicExpression.ParseLambda(parameters, typeof(int), expression, new object[0]); Delegate @delegate = lambdaExpression.Compile(); return(@delegate as Func <T, T, int>); }
public void CanParseNestedLambdasWithOuterVariableReference() { var expression = "resource.Any(allowed.Contains(it_1.Item1))"; var parameters = new[] { Expression.Parameter(typeof(Tuple <string>[]), "resource"), Expression.Parameter(typeof(string[]), "allowed"), }; var expr = (Expression <Func <Tuple <string>[], string[], bool> >)DynamicExpression .ParseLambda(parameters, typeof(bool), expression); Console.WriteLine(expr); Assert.NotNull(expr); var func = expr.Compile(); Assert.True(func(new[] { Tuple.Create("1"), Tuple.Create("2") }, new[] { "1", "3" })); Assert.False(func(new[] { Tuple.Create("1"), Tuple.Create("2") }, new[] { "3" })); }
/// <summary> /// Projects each element of a sequence to an <see cref="IQueryable"/> and combines the /// resulting sequences into one sequence. /// </summary> /// <param name="source">A sequence of values to project.</param> /// <param name="selector">A projection string expression to apply to each element.</param> /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param> /// <returns>An <see cref="IQueryable"/> whose elements are the result of invoking a one-to-many projection function on each element of the input sequence.</returns> public static IQueryable SelectMany(this IQueryable source, string selector, params object[] args) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (selector == null) { throw new ArgumentNullException(nameof(selector)); } #if NET35 if (string.IsNullOrEmpty(selector) || selector.All(c => Char.IsWhiteSpace(c))) #else if (string.IsNullOrWhiteSpace(selector)) #endif { throw new ArgumentException("Expected non-empty string", nameof(selector)); } LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, args); //Extra help to get SelectMany to work from StackOverflow Answer //http://stackoverflow.com/a/3001674/2465182 //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is. Type inputType = source.Expression.Type.GetGenericArguments()[0]; Type resultType = lambda.Body.Type.GetGenericArguments()[0]; Type enumerableType = typeof(IEnumerable <>).MakeGenericType(resultType); Type delegateType = typeof(Func <,>).MakeGenericType(inputType, enumerableType); lambda = Expression.Lambda(delegateType, lambda.Body, lambda.Parameters); return(source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "SelectMany", new Type[] { source.ElementType, resultType }, source.Expression, Expression.Quote(lambda)))); }
/// <summary> /// Groups the elements of a sequence according to a specified key string function /// and creates a result value from each group and its key. /// </summary> /// <param name="source">A <see cref="IQueryable"/> whose elements to group.</param> /// <param name="keySelector">A string expression to specify the key for each element.</param> /// <param name="resultSelector">A string expression to specify a result value from each group.</param> /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param> /// <returns>A <see cref="IQueryable"/> where each element represents a projection over a group and its key.</returns> /// <example> /// <code> /// var groupResult1 = qry.GroupBy("NumberPropertyAsKey", "StringProperty"); /// var groupResult2 = qry.GroupBy("new (NumberPropertyAsKey, StringPropertyAsKey)", "new (StringProperty1, StringProperty2)"); /// </code> /// </example> public static IQueryable GroupBy(this IQueryable source, string keySelector, string resultSelector, object[] args) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (string.IsNullOrEmpty(keySelector?.Trim())) { throw new ArgumentNullException(nameof(keySelector)); //string.IsNullOrWhiteSpace not available in NET35 } if (string.IsNullOrEmpty(resultSelector?.Trim())) { throw new ArgumentNullException(nameof(resultSelector)); //string.IsNullOrWhiteSpace not available in NET35 } LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, args); LambdaExpression elementLambda = DynamicExpression.ParseLambda(source.ElementType, null, resultSelector, args); return(source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "GroupBy", new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type }, source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)))); }
/// <summary> /// Projects each element of a sequence to an <see cref="IQueryable"/> /// and invokes a result selector function on each element therein. The resulting /// values from each intermediate sequence are combined into a single, one-dimensional /// sequence and returned. /// </summary> /// <param name="source">A sequence of values to project.</param> /// <param name="collectionSelector">A projection function to apply to each element of the input sequence.</param> /// <param name="resultSelector">A projection function to apply to each element of each intermediate sequence.</param> /// <param name="collectionSelectorArgs">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param> /// <param name="resultSelectorArgs">An object array that contains zero or more objects to insert into the predicate as parameters. Similar to the way String.Format formats strings.</param> /// <returns> /// An <see cref="IQueryable"/> whose elements are the result of invoking the one-to-many /// projection function <paramref name="collectionSelector"/> on each element of source and then mapping /// each of those sequence elements and their corresponding source element to a result element. /// </returns> public static IQueryable SelectMany(this IQueryable source, string collectionSelector, string resultSelector, object[] collectionSelectorArgs = null, object[] resultSelectorArgs = null) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (string.IsNullOrEmpty(collectionSelector?.Trim())) { throw new ArgumentNullException(nameof(collectionSelector)); //string.IsNullOrWhiteSpace not available in NET35 } if (string.IsNullOrEmpty(resultSelector?.Trim())) { throw new ArgumentNullException(nameof(resultSelector)); //string.IsNullOrWhiteSpace not available in NET35 } LambdaExpression sourceSelectLambda = DynamicExpression.ParseLambda(source.ElementType, null, collectionSelector, collectionSelectorArgs); //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is. Type sourceLambdaInputType = source.Expression.Type.GetGenericArguments()[0]; Type sourceLambdaResultType = sourceSelectLambda.Body.Type.GetGenericArguments()[0]; Type sourceLambdaEnumerableType = typeof(IEnumerable <>).MakeGenericType(sourceLambdaResultType); Type sourceLambdaDelegateType = typeof(Func <,>).MakeGenericType(sourceLambdaInputType, sourceLambdaEnumerableType); sourceSelectLambda = Expression.Lambda(sourceLambdaDelegateType, sourceSelectLambda.Body, sourceSelectLambda.Parameters); //we have to create additional lambda for result selection ParameterExpression xParameter = Expression.Parameter(source.ElementType, "x"); ParameterExpression yParameter = Expression.Parameter(sourceLambdaResultType, "y"); LambdaExpression resultSelectLambda = DynamicExpression.ParseLambda(new[] { xParameter, yParameter }, null, resultSelector, resultSelectorArgs); Type resultLambdaResultType = resultSelectLambda.Body.Type; return(source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "SelectMany", new Type[] { source.ElementType, sourceLambdaResultType, resultLambdaResultType }, source.Expression, Expression.Quote(sourceSelectLambda), Expression.Quote(resultSelectLambda)))); }
/// <summary> /// Projects each element of a sequence to an <see cref="IQueryable"/> and combines the /// resulting sequences into one sequence. /// </summary> /// <param name="source">A sequence of values to project.</param> /// <param name="selector">A projection string expression to apply to each element.</param> /// <param name="args">An object array that contains zero or more objects to insert into the predicate as parameters. Similiar to the way String.Format formats strings.</param> /// <returns>An <see cref="IQueryable"/> whose elements are the result of invoking a one-to-many projection function on each element of the input sequence.</returns> public static IQueryable SelectMany(this IQueryable source, string selector, params object[] args) { Validate.Argument(source, "source").IsNotNull().Check() .Argument(selector, "selector").IsNotNull().IsNotEmpty().IsNotWhiteSpace().Check(); LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, args); //Extra help to get SelectMany to work from StackOverflow Answer //http://stackoverflow.com/a/3001674/2465182 //we have to adjust to lambda to return an IEnumerable<T> instead of whatever the actual property is. Type inputType = source.Expression.Type.GetGenericArguments()[0]; Type resultType = lambda.Body.Type.GetGenericArguments()[0]; Type enumerableType = typeof(IEnumerable <>).MakeGenericType(resultType); Type delegateType = typeof(Func <,>).MakeGenericType(inputType, enumerableType); lambda = Expression.Lambda(delegateType, lambda.Body, lambda.Parameters); return(source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "SelectMany", new Type[] { source.ElementType, resultType }, source.Expression, Expression.Quote(lambda)))); }
public static Expression <Func <T, S> > ParseLambda <T, S>(string expression, params object[] values) { return((Expression <Func <T, S> >)DynamicExpression.ParseLambda(typeof(T), typeof(S), expression, values)); }