Dynamically created expressions

I create a dynamic expression that will order the elements in the list according to some rule (lambda exp.). This is the code:

Expression<Func<String, String>> exp = o => o;

MethodCallExpression orderByExp = Expression.Call(typeof(Enumerable), "OrderBy",
    new Type[] { typeof(String), exp.Body.Type }, Expression.Parameter(typeof(IEnumerable<String>), "list"), exp);

Now I want to execute the previously created expression for specific data to sort it, but it does not work due to some strange exceptions, such as "Lambda Parameter not in scope" or "Argument expression is not valid".

var data = new String[] { "asdasdasd", "asdads", "123", "xcvxcvs", "ASDSD" };

// one of attempts: doesn't work
var result = data.AsQueryable().Provider.CreateQuery<String>(orderByExp);

Can someone help me with this?

+3
source share
4 answers

This is the working code:

Expression<Func<String, String>> exp = o => o;
var list = Expression.Parameter(typeof(IEnumerable<String>), "list");

MethodCallExpression orderByExp = Expression.Call(typeof(Enumerable), "OrderBy",
    new Type[] { typeof(String), exp.Body.Type }, list, exp);

var lambda = Expression.Lambda<Func<IEnumerable<String>, IEnumerable<String>>>(orderByExp, list);
var data = new String[] { "asdasdasd", "asdads", "123", "xcvxcvs", "ASDSD" };
var result = lambda.Compile()(data);
  • To execute the MethodCallExpression expression, you must wrap it in a lambda expression.
  • , ('list'), MethodCallExpression LambdaExpression, , : "Lambda Parameter in the scope" .

+2

( ):

public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> items, string property, bool ascending)
        {
            var MyObject = Expression.Parameter(typeof (T), "MyObject");
            var MyEnumeratedObject = Expression.Parameter(typeof (IEnumerable<T>), "MyEnumeratedObject");
            var MyProperty = Expression.Property(MyObject, property);
            var MyLamda = Expression.Lambda(MyProperty, MyObject);
            var MyMethod = Expression.Call(typeof(Enumerable), ascending ? "OrderBy" : "OrderByDescending", new[] { typeof(T), MyLamda.Body.Type }, MyEnumeratedObject, MyLamda);
            var MySortedLamda = Expression.Lambda<Func<IEnumerable<T>, IOrderedEnumerable<T>>>(MyMethod, MyEnumeratedObject).Compile();
            return MySortedLamda(items);
        }
+3

Linq, , :

<Extension()> _
Public Function OrderBy(Of T)(ByVal query As IEnumerable(Of T), ByVal sortColumn As String, ByVal direction As String) As IEnumerable(Of T)
        Dim methodName As String = String.Format("OrderBy{0}", If(direction.ToLower() = "asc", "", "Descending"))
        Dim parameter As ParameterExpression = Expression.Parameter(GetType(T), "p")
        Dim memberAccess As MemberExpression = Nothing

        For Each _property As Object In sortColumn.Split(".")
            memberAccess = MemberExpression.Property(If(memberAccess, CType(parameter, Expression)), _property)
        Next

        Dim orderByLambda As LambdaExpression = Expression.Lambda(memberAccess, parameter)
        '
        Dim myEnumeratedObject As ParameterExpression = Expression.Parameter(GetType(IEnumerable(Of T)), "MyEnumeratedObject")

        Dim result As MethodCallExpression = Expression.Call(GetType(Enumerable), _
                  methodName, _
                  New System.Type() {GetType(T), memberAccess.Type}, _
                  myEnumeratedObject, _
                  orderByLambda)

        Dim lambda = Expression.Lambda(Of Func(Of IEnumerable(Of T), IEnumerable(Of T)))(result, myEnumeratedObject)
        Return lambda.Compile()(query)
    End Function
+1

- , :

data.AsQueryable().OrderBy(exp);

Do you even need to use IQueryablehere? I have the feeling that I am missing some big picture. Are you going to call this part of LINQ to SQL (or LINQ to Entities)? If it is only in LINQ to Objects, can't you just use data.OrderBy(exp)?

In principle, it would be useful to clarify the following :)

0
source

Source: https://habr.com/ru/post/1705804/


All Articles