How to convert lambda to expression trees format?

3

How to convert this lambda:

Set.AsQueryable (). Where ( profile => Profile.CostCenters.Select (CostCentre => CostCentre.Id) .Any (Id => Ids.Contains (Id)) ) .ToList ()

Currently I've been able to do the following: profile.CostCenters.Select (CostCentre => CostCentre.Id) and I'm stopped at how to do the .Any (Id => Ids. Contains (Id))

static void Main(string[] args)
{
    var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);

    Ids = AboveLambdaConvertedToExpressionTree(profileExample);

    var result = Set.AsQueryable().Where(Profile => Profile.CostCenters.Select(CostCentre => CostCentre.Id).Any(Id => Ids.Contains(Id))).ToList();

    //Expression<Func<Profile, bool>> lambda = (Profile) => Profile.CostCenters.Select(CostCentre => CostCentre.Id).Any(Id => Ids.Contains(Id));

    var id = Expression.Parameter(typeof(long), "Id");
    var costCentre = Expression.Parameter(typeof(CostCentre), "CostCentre");
    var profile = Expression.Parameter(typeof(Profile), "Profile");
    var selectLambda = Expression.Lambda(Expression.PropertyOrField(costCentre, "Id"), costCentre);
    var selectCall = Expression.Call(typeof(Enumerable),
                             "Select",
                             new Type[] { typeof(CostCentre), typeof(long) }, 
                             Expression.PropertyOrField(profile, "CostCenters"),
                             selectLambda);                                   
}

For more details follow the complete code below:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressionTrees
{
    class Program
    {
        static void Main(string[] args)
        {
            var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);

            Ids = AboveLambdaConvertedToExpressionTree(profileExample);

            var result = Set.AsQueryable().Where(profile => profile.CostCenters.Select(CostCentre => CostCentre.Id).Any(Id => Ids.Contains(Id))).ToList();
            //How to convert above lambda to expression tree?????
            //NowThatAboveLambdaConvertedToExpressionTree(Set);

            //Expression<Func<Profile, bool>> lambda = (profile) => profile.CostCenters.Select(CostCentre => CostCentre.Id).Any(Id => Ids.Contains(Id));
            //Convert that is great too!

            //var result = Set.AsQueryable().Where(lambda).ToList(); 
            //Same result

            //Expected result result.Count == 2
        }
        static IEnumerable<Int64> AboveLambdaConvertedToExpressionTree(Profile profileExample)
        {
            // I show that as example of what i need to do

            //Begin     var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);
            var property = profileExample.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name != "Id").First();
            var collection = ((IEnumerable)property.GetValue(profileExample, null)).AsQueryable();
            var collectionType = property.PropertyType.GetGenericArguments()[0];
            var collectionTypeName = collectionType.Name;

            var keyType = typeof(Int64);
            var keyName = "Id";
            //BeginWhere
            var parameter = Expression.Parameter(collectionType, collectionTypeName);

            var profileExampleWhere = Expression.Lambda(
                                                Expression.NotEqual(parameter, Expression.Constant(null)),
                                                parameter);

            var profileExampleWhereCall = Expression.Call(typeof(Enumerable),
                                                                    "Where",
                                                                    new Type[] { collectionType },
                                                                    collection.Expression,
                                                                    profileExampleWhere);
            //EndWhere

            //BeginSelect
            var profileExampleSelect = Expression.Lambda(Expression.PropertyOrField(parameter, keyName),
                                             parameter);

            var profileExampleSelectCall = Expression.Call(typeof(Enumerable),
                                                      "Select",
                                                      new Type[] { collectionType, keyType },
                                                      profileExampleWhereCall,
                                                      profileExampleSelect);



            var Ids = Expression.Lambda(profileExampleSelectCall).Compile().DynamicInvoke();
            //EndSelect
            //End     var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);

            return ((IEnumerable)Ids).Cast<Int64>();
        }
        public partial class Profile
        {
            public virtual Int64 Id { get; set; }

            public virtual ICollection<CostCentre> CostCenters { get; set; }
        }


        public partial class CostCentre
        {
            public virtual Int64 Id { get; set; }
        }
        public static Profile profileExample
        {
            get
            {
                return new Profile()
                {
                    Id = 1,
                    CostCenters = new List<CostCentre>() { new CostCentre() { Id = 2 } }
                };
            }
        }

        public static IList<Profile> Set
        {
            get
            {
                return new List<Profile>() { new Profile() { Id = 1, 
                                                            CostCenters = new List<CostCentre>() {  new CostCentre() { Id = 1 }, 
                                                                                                    new CostCentre() { Id = 2 } } 
                                                          },            
                                            new Profile() { Id = 2, 
                                                            CostCenters = new List<CostCentre>() {  new CostCentre() { Id = 2 }, 
                                                                                                    new CostCentre() { Id = 3 } } 
                                            },
                                            new Profile() { Id = 3, 
                                                            CostCenters = new List<CostCentre>() {  new CostCentre() { Id = 3 } } 
                                            } };
            }
        }
    }
}
    
asked by anonymous 11.06.2014 / 14:31

1 answer

2

Solved with the help of Microsoft's Mads.

class Program
{
    static void Main(string[] args)
    {
        //var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);

        var Ids = AboveLambdaConvertedToExpressionTree(profileExample);

        //var result = Set.AsQueryable().Where(Profile => Profile.CostCenters.Select(CostCentre => CostCentre.Id).Any(Id => Ids.Contains(Id))).ToList();

        var id = Expression.Parameter(typeof(long), "Id");
        var costCentre = Expression.Parameter(typeof(CostCentre), "CostCentre");
        var profile = Expression.Parameter(typeof(Profile), "Profile");
        var selectLambda = Expression.Lambda(Expression.PropertyOrField(costCentre, "Id"), costCentre);
        var selectCall = Expression.Call(typeof(Enumerable),
                                 "Select",
                                 new Type[] { typeof(CostCentre), typeof(long) }, 
                                 Expression.PropertyOrField(profile, "CostCenters"),
                                 selectLambda);                      

        //var id2 = Expression.Parameter(typeof(long), "Id");

        var containsCall = Expression.Call(typeof(Enumerable),
                              "Contains",
                              new Type[] { typeof(long) },
                              Expression.Constant(Ids),
                              id);

        var anyLambda = Expression.Lambda(containsCall, id);

        var anyCall = Expression.Call(typeof(Enumerable),
                     "Any",
                     new Type[] { typeof(long) },
                     selectCall,
                     anyLambda);

        var whereLambda = Expression.Lambda(anyCall, profile);

        var callExpression = Expression.Call(typeof(Queryable),
                                                    "Where",
                                                    new Type[] { typeof(Profile) },
                                                    Set.AsQueryable().Expression,
                                                    whereLambda);


        var result = Expression.Lambda(callExpression).Compile().DynamicInvoke();


    }
    
12.06.2014 / 02:00