如何在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返回)和任何给定的属性名称和导航来构建它们,如示例中所示。

如何在c#中为任何实体、任何属性和导航构建通用Lambda表达式

我不确定我是对的你想做什么,但例如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 });