views:

627

answers:

2

Hi,

Suppose I have an entity object defined as

public partial class Article  
{  
    public Id
    {
        get;
        set;
    }  
    public Text
    {
        get;
        set;
    }  
    public UserId
    {
        get;
        set;
    }  
}

Based on some properties of an Article, I need to determine if the article can be deleted by a given user. So I add a static method to do the checking. Something like:

public partial class Article  
{  
    public static Expression<Func<Article, bool>> CanBeDeletedBy(int userId)
    {  
        //Add logic to be reused here
        return a => a.UserId == userId;
    }  
}

So now I can do

using(MyEntities e = new MyEntities())  
{
    //get the current user id
    int currentUserId = 0;

    e.Articles.Where(Article.CanBeDeletedBy(currentUserid));  
}

So far so good. Now I want to reuse the logic in CanBeDeletedBy while doing a Select, something like:

using(MyEntities e = new MyEntities())  
{
    //get the current user id
    int currentUserId = 0;

    e.Articles.Select(a => new  
    {  
        Text = a.Text,  
        CanBeDeleted = ???  
    };  
}

But no matter what I try, I can't use the expression in the select method. I guess that If I can do

    e.Articles.Select(a => new  
    {  
        Text = a.Text,  
        CanBeDeleted = a => a.UserId == userId
    };  

Then I should be able to use the same expression. Tried to compile the expression and call it by doing

    e.Articles.Select(a => new  
    {  
        Text = a.Text,  
        CanBeDeleted = Article.CanBeDeletedBy(currentUserId).Compile()(a)
    }; 

but it won't work either.

Any ideas on how to get this to work? Or if it isn't possible, what are the alternatives to reuse business logic in both places?

Thanks

Pedro

+1  A: 

Re-using expression trees is a black art; you can do it, but you would need to switch a lot of code to reflection and you'd lose all the static checking. In particular, working with the anonymous types becomes a nightmare (although dynamic in 4.0 might be workable).

Further, if you cheat and use Expression.Invoke, then it isn't supported by all providers (most noticeably not on EF in .NET 3.5SP1).

Unless this is a major pain point, I'd leave it with duplication. Or do you need to re-use the expression tree?

Marc Gravell
Don't really need to re-use the expression tree. It was just to try not duplicate security related code. But I will do it for now, and see if I can refactor the code later.Thanks
Pedro