简体   繁体   中英

LINQ: use Expression inside Where with anonymous type

Goal: call a method that returns an Expression I can use to chain methods on an anonymous IQueryable.

Example:

var allProducts = from p in ctx.Products;
var customWhere = Product.GiveMeYourQuery();
var productsIWant = allProducts.Where(customWhere);
Console.Writeline("yeaaaaah!");

This is what I've come up with as to now, which, of course, doesn't work:

class MainClass
    {
        public static void Main(string[] args)
        {
            var list = new [] {
                new { Name = "ciao", Age = 18 },
                new { Name = "prova", Age = 28 },
                new { Name = "mah", Age = 38 },
                new { Name = "boh", Age = 48 }
            };

            var myAnon = list.Where(x => x.Name.Length > 2).AsQueryable();
            var thisthat = new MainClass();

            var subset = myAnon.Where(thisthat.Where);
        }

        public Expression<Func<T, bool>> Where<T>(T anon){
            var expr = Expression.Lambda(Expression.Equal(Expression.Constant(anon), Expression.Constant(anon)));

            return (Expression<Func<T, bool>>) expr;
        }
    }

Compiler wisdom: ../Program.cs(24,24): Error CS0407: A method or delegate 'System.Linq.Expressions.Expression LINQInjector.MainClass.Where(anonymous type)' return type does not match delegate `bool System.Func(anonymous type)' return type (CS0407) (LINQInjector)

I feel I'm pretty close, but I cannot really see the path.

Unfortunately I cannot just cast the a' object to a type I create because what the program should output is the SQL (yes, I'm basically building a querybuilder that feeds another tier the queries to execute) and because I'd have to create too many types anyway (each type for each possible chain of joins between tens of tables).

EDIT:

While I appreciate you trying to show me alternatives and workarounds, at this point I think there's none. This is my question: how to inject Expressions into an anonymous type. If this cannot be done just say so.

Since you want to access a property known at compile time of an object outside of the scope in which it's created, you don't want to use an anonymous object. An anonymous object would be appropriate if you're accessing it using lambdas created in the same scope in which the anon object is created, but you don't want to do that. You want to have another method statically access a property of that object. Just give it a name, it'll make everything super easy:

public class Foo 
{
    public string Name{get;set;} 
    //...
}

public static Expression<Func<Foo, bool>> NameEquals(string name)
{
    return foo => foo.Name == name;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM