开发者

How to pass a C# Select () extension delegate or expression to a Repository?

Everyone projects once in a while:

 var c = dc.Products.Select( p => new {p.id, p.name});
 // results in c having properties of .id and .name

What if I want to refactor that in to a method. How would I pass the Select parameter?

var c = myFunction( p => new {p.id, p.name});

Product myFunction( ??? myLambda)
{
    var c = dc.Products.Select( myLambda);

    var result = new Product();
    foreach( var myproperty in //property in myLambda)
    {
        result.XX // p开发者_JS百科roperty that matches, set it equal to myproperty
    }
}

Obviously, I need to figure out reflection a lot more. :)


The type of the parameter should be something like Expression<Func<Product,object>>. Also, I think you need your function to return an IEnumerable<Product> with the properties set.

IEnumerable<Product> myFunction( Expression<Func<Product,object>> selector )
{
    var products = new List<Product>();
    foreach (var c in dc.Products.Select( selector ))
    {
        var product = new Product();
        foreach (var property in c.GetType().GetProperties())
        {
            var productProperty = typeof(Product).GetProperty( property.Name );
            productProperty.SetValue( product, property.GetValue( c, null ) );
        }
        products.Add( product );
    }
    return products;
}

Having said that I think I would probably have a separate model for each combination of properties being returned and use a generic method to return one of those.

IEnumerable<T> ProductPartial<T>( Func<Product,T> selector ) where T : new
{
      return dc.Products.ToList().Select( selector );
}

used as

var pricing = repository.ProductPartial( p => new PricingModel( p ) );

Note: After thinking about it a little, if you are going to return a separate model, I think you may need to realize the query before you can do the conversion to the model anyway. In that case a Func<Product,T> is probably most appropriate -- I've thrown an explicit ToList() in to make sure that the query is realized first so the select doesn't fail. If it were a Where clause, that would be different. Even though this is slightly less efficient from a data transfer perspective (you're retrieving all the properties), I still prefer using using the specific model if you feel like you need to put the selection in the repository. Since you're only selecting part of the properties it feels wrong to pretend that you have an actual Product instance when you really don't.


You could at least look at any exists LINQ definitions, like http://msdn.microsoft.com/en-us/library/bb548891.aspx

So you need Func<TSource, TResult> myLambda

To be precise:

TResult myFunction<TResult>(Expression<Func<Product, TResult>> myLambda)

or

IEnumerable<TResult> myFunction<TResult>(Expression<Func<Product, TResult>> myLambda)

UPD: according to the @tvanfosson comment - the code has been changed a little.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜