如何在c#中为任何实体、任何属性和导航构建通用Lambda表达式
本文关键字:任何 导航 构建 表达式 Lambda 属性 实体 | 更新日期: 2023-09-27 17:50:51
我想有人帮助我建立lambda表达式,以便通过反射成为通用的。我有以下函数,它按名称返回实体类型:
private Type GetEntityType(string EntityName)
{
Assembly Data = Assembly.Load("Domain.Entities");
Type type = Data.GetTypes()
.Where(t => t.IsClass && t.Namespace == "Domain.Entities" && t.Name == EntityName)
.ToList<Type>().First();
return type;
}
因此,如果我有一些相关的实体,例如客户,购买和项目:
public partial class Customers
{
public Customers()
{
this.Purchases = new HashSet<Purchases>();
}
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Purchases> Purchases { get; set; }
}
public partial class Purchases
{
public Purchases()
{
}
[Key]
public int Id { get; set; }
public Date DatePurchased { get; set; }
public virtual Customers Customers { get; set; }
public virtual Items Items { get; set; }
}
public partial class Items
{
public Items()
{
this.Purchases = new HashSet<Purchases>();
}
[Key]
public int Id { get; set; }
public string NameOfItem { get; set; }
public virtual ICollection<Purchases> Purchases { get; set; }
}
我可以有客户的表达式,如:
c => c.Name
c => c.Name == "My name"
c => c.Name.Contains("My name")
对于购买,我可以有:
p => p.Customers
p => p.Customers.Name
p => p.Customers.Name == "My Name"
p => p.Customers.Name.Contains("My Name")
我还可以从客户导航到项目属性…但这对我来说是进一步的一步,因为我首先需要将这些表达式转换为泛型,以便通过我们知道其名称的任何给定实体(由上面的函数GtEntityType返回)和任何给定的属性名称和导航来构建它们,如示例中所示。
我不确定我是对的你想做什么,但例如lambda:
Type t = this.GetEntityType("Customers");
ParameterExpression parameter = System.Linq.Expressions.Expression.Parameter(t);
System.Linq.Expressions.Expression property = System.Linq.Expressions.Expression.Property(parameter, "Purchases");
LambdaExpression lambda = System.Linq.Expressions.Expression.Lambda(property, parameter);
之后你可以这样使用:
MethodInfo selectQueryable = typeof(Queryable)
.GetMethods()
.Where(method => method.Name == "Select")
.Select(method => new { M = method, P = method.GetParameters() })
.Where(x => x.P.Length == 2
&& x.P[0].ParameterType.IsGenericType
&& x.P[0].ParameterType.GetGenericTypeDefinition() == typeof(IQueryable<>)
&& x.P[1].ParameterType.IsGenericType
&& x.P[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>))
.Select(x => new { x.M, A = x.P[1].ParameterType.GetGenericArguments() })
.Where(x => x.A.Length == 1
&& x.A[0].IsGenericType
&& x.A[0].GetGenericTypeDefinition() == typeof(Func<,>))
.Select(x => x.M)
.Single()
.MakeGenericMethod(t,typeof(Purchases));
var s = selectQueryable.Invoke(null, new[] { dbSet, lambda });