[英]C# : Combine two generic expression trees
我有兩個表達式樹:一個用於獲取類的導航屬性,另一個用於過濾來自此導航屬性的值:我正在嘗試將它們組合起來。
class Program
{
public interface IDeletable
{
bool IsDeleted { get; set; }
}
public class User
{
public int Id { get; set; }
public IEnumerable<BlogPost> BlogPosts;
}
public class BlogPost : IDeletable
{
public string Text { get; set; }
public bool IsDeleted { get; set; }
}
static void Main(string[] args)
{
var user = new User()
{
Id = 1,
BlogPosts = new List<BlogPost> {
new BlogPost {IsDeleted=false,Text="hello" },
new BlogPost {IsDeleted=true,Text="this is deleted" }
}
};
Expression<Func<User, IEnumerable<BlogPost>>> notDeletedExpression = Combine<User, BlogPost>(x => x.BlogPosts, x => !x.IsDeleted);
Console.ReadLine();
}
public static Expression<Func<T, IEnumerable<TChild>>> Combine<T, TChild>
(
Expression<Func<T, IEnumerable<TChild>>> navigationProperty,
Expression<Func<TChild, bool>> filter
)
where T : class
where TChild : class, IDeletable
{
//TODO
// shourld return x=>x.Posts.Where(p=>IsDeleted==false) ;
return null;
}
}
在下面的示例中,您的示例中的兩個表達式使用Enumerable.Where
方法組合:
public static Expression<Func<T, IEnumerable<TChild>>> Combine<T, TChild>
(
Expression<Func<T, IEnumerable<TChild>>> navigationProperty,
Expression<Func<TChild, bool>> filter
)
where T : class
where TChild : class, IDeletable
{
// Consider caching the MethodInfo object:
var whereMethodInfo = GetEnumerableWhereMethodInfo<TChild>();
// Produce an Expression tree like:
// Enumerable.Where(<navigationProperty>, <filter>)
var filterExpr = Expression
.Call(
whereMethodInfo,
navigationProperty.Body,
filter
);
// Create a Lambda Expression with the parameters
// used for `navigationProperty` expression
return Expression
.Lambda<Func<T, IEnumerable<TChild>>>(
filterExpr,
navigationProperty.Parameters
);
}
private static MethodInfo GetEnumerableWhereMethodInfo<TSource>()
{
// Get a MethodInfo definition for `Enumerable.Where<>`:
var methodInfoDefinition = typeof(Enumerable)
.GetMethods()
.Where(x => x.Name == nameof(Enumerable.Where))
.First(x =>
{
var parameters = x.GetParameters();
return
parameters.Length == 2 &&
parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>) &&
parameters[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>);
});
// Get a MethodInfo object for `Enumerable.Where<TSource>`:
var methodInfo = methodInfoDefinition.MakeGenericMethod(typeof(TSource));
return methodInfo;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.