Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq 从propertypath生成Lambda表达式_Linq_Lambda - Fatal编程技术网

Linq 从propertypath生成Lambda表达式

Linq 从propertypath生成Lambda表达式,linq,lambda,Linq,Lambda,嗨,假设我有一个属性路径,如下所示 我们可以说,我有一篇文章有增值税,增值税有价值。 现在我想使用Linq使用该属性路径对列表进行排序 当字符串中有“Vat.Value”并且希望得到以下结果时,如何构建lambda表达式 list.Order(x => x.Vat.Value) 我并不总是知道增值税的类型和价值,有时它只是我想要的x.名称。我不确定我是否完全理解这个问题,但类似这样的东西看起来就像你想要的。请注意,为了清晰起见,我可能会在生产中将lambda重构为一个helper方法。还

嗨,假设我有一个属性路径,如下所示

我们可以说,我有一篇文章有增值税,增值税有价值。 现在我想使用Linq使用该属性路径对列表进行排序 当字符串中有“Vat.Value”并且希望得到以下结果时,如何构建lambda表达式

list.Order(x => x.Vat.Value)

我并不总是知道增值税的类型和价值,有时它只是我想要的x.名称。

我不确定我是否完全理解这个问题,但类似这样的东西看起来就像你想要的。请注意,为了清晰起见,我可能会在生产中将lambda重构为一个helper方法。还请注意,使用这样的反射可能会对性能造成很大影响,具体取决于您的集合有多大

[Test]
public void OrderByUsingReflection()
{
    var values = new[] 
    {
        new { Vat = new { Value = "two"}},
        new { Vat = new {Value = "one"}},
    };

    var result = values.OrderBy(x =>
    {
        var vat = x.GetType().GetProperty("Vat").GetValue(x, null);
        return vat.GetType().GetProperty("Value").GetValue(vat, null);
    });

    Assert.AreEqual(result.ToList()[0], values[1]);
    Assert.AreEqual(result.ToList()[1], values[0]);
}

我用扩展方法修复了它。例如,现在使用propertypath的方法是

var orderedArticles = articles.OrderBy("Vat.Value");
而不是

var orderedArticles = articles.OrderBy(x => x.Vat.Value)
扩展方法:

private static Func<T, TReturnType> GetLambda<T, TReturnType>(IEnumerable<string> propertyNames)
{
    var rootParameterExression = Expression.Parameter(typeof(T));

    Expression expression = rootParameterExression;
    foreach (var propertyName in propertyNames)
    {
        expression = Expression.Property(expression, propertyName);
    }
    return Expression.Lambda<Func<T, TReturnType>>(expression, rootParameterExression).Compile();
}

public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> queryable, string propertyPath)
{
    var propertyPathList = propertyPath.Split(Convert.ToChar("."));
    Type propertyType = typeof(T);
    foreach (var propertyName in propertyPathList)
    {
        propertyType = propertyType.GetProperty(propertyName).PropertyType;
    }

    if(propertyType == typeof(decimal))
    {
        var lambda = GetLambda<T, Decimal>(propertyPathList);
        return queryable.OrderBy(lambda);
    }
    var lamda = GetLambda<T, object>(propertyPathList);
    return queryable.OrderBy(lamda);
}
private static Func GetLambda(IEnumerable propertyNames)
{
var rootParameterExression=Expression.Parameter(typeof(T));
表达式=根参数表达式;
foreach(propertyNames中的变量propertyName)
{
expression=expression.Property(expression,propertyName);
}
返回表达式.Lambda(表达式,rootParameterExression.Compile();
}
公共静态IOrderedEnumerable OrderBy(此IEnumerable可查询,字符串属性路径)
{
var propertyPathList=propertyPath.Split(Convert.ToChar(“.”);
类型属性类型=类型(T);
foreach(PropertyPath列表中的变量propertyName)
{
propertyType=propertyType.GetProperty(propertyName).propertyType;
}
if(propertyType==typeof(十进制))
{
var lambda=GetLambda(PropertyPath列表);
返回可查询的.OrderBy(lambda);
}
var lamda=GetLambda(propertyPathList);
返回可查询的订购人(lamda);
}

有什么原因使您不能使用现有的LINQ动态查询库,因为该库具有接受字符串的重载


它可能与您刚刚编写的代码相同,但它的代码您不必维护,并且可能有一些优化。

我认为我现在发布的代码更高效,更易于使用。