The Muffin Man
The Muffin Man

Reputation: 20004

Passing lambda expression as parameter

I've got a few tables that all have the same column domainID which basically just controls what data gets displayed on which website, as they share a database.

So when I go to databind a table to a control I would need to create a large switch to handle the different LINQ queries. I would like to create a utility method which takes the table type as a parameter and then return a where clause based on a column in passed table.

public static IEnumerable<T> ExecuteInContext<T>(
               IQueryable<T> src)
        {
             int domain = 1;//hard coded for example

             return src.Where(x => x.DomainID == domain);//Won't work, has to be a way to do this.            
        }

I'm stuck on the return code. You can't simply construct a where clause like I currently am because it doesn't know what table i'm talking about.

I'm trying to call that first method like this:

using (DataClasses1DataContext db = new DataClasses1DataContext())
        {

            var q = Utility.ExecuteInContext(db.GetTable<item>());

            Repeater1.DataSource = q;
            Repeater1.DataBind();
        }

I hope this explains what I'm trying to do.

Edit: BrokenGlass's answer solved my problem. I would like to add that you need to open up your .dbml.cs file and extend the table/class with your interface. I also wanted to point out that the project wouldn't build if my column was nullable, it said it wasn't the same return type as my interface.

Upvotes: 0

Views: 2027

Answers (4)

Akash Kava
Akash Kava

Reputation: 39916

Expression pe = Expression.Parameter(typeof(T));
Expression prope = Expression.Property(pe, "DomainID");
Expression ce = Expression.Equals(prope, 
    Expression.Constant((int)1);

Expression<Func<T,bool>> exp =
Expression.Lambda<Func<T,bool>>(
    ce, pe);

return query.Where(exp);

Upvotes: 2

Haplo
Haplo

Reputation: 1368

I'm not sure if I understand what you mean, but maybe you want to add a where clause:

public static IEnumerable<T> ExecuteInContext<T>(IQueryable<T> src)     

     where T: MyType //MyType exposing your DomainId   
    {             
       int domain = 1;//hard coded for example            
        return src.Where(x => x.DomainID == domain);//Won't work, has to be a way to do this.                    
    }

Upvotes: 0

BrokenGlass
BrokenGlass

Reputation: 160852

You have to restrict your T to a class that has a property of DomainID - you can add these interface implementations in partial classes that extend your data model.

public interface IFoo
{
    int DomainId { get; set; }
}
..

public static IQueryable<T> ExecuteInContext<T>(IQueryable<T> src) where T: IFoo
{
  int domain = 1;//hard coded for example
  return src.Where(x => x.DomainID == domain);
}

Upvotes: 3

Dan J
Dan J

Reputation: 16708

You should be able to cast your generic parameter to the intended type...

public static IEnumerable<T> ExecuteInContext<T>(IQueryable<T> src)
{
    int domain = 1;//hard coded for example

    return src.Where(x => ((T)x).DomainID == domain);
}

But you realize you've created a generic method that assumes its type parameter will always expose a specific property? If you're going to do that, you should apply a generic type constraint such that T is always derived from a type that has that property...

For example:

public static IEnumerable<T> ExecuteInContext<T>(IQueryable<T> src) where T : IMyDomainObject

Upvotes: 0

Related Questions