C# 通过扩展方法将LambdaExpression转换为表达式
我看了这个问题的其他版本,但似乎抛弃一种方法对其他人有效。我不确定我在这里做错了什么。我对Linq的表达能力建设部分还不熟悉 我的扩展方法如下:C# 通过扩展方法将LambdaExpression转换为表达式,c#,linq,lambda,extension-methods,linq-expressions,C#,Linq,Lambda,Extension Methods,Linq Expressions,我看了这个问题的其他版本,但似乎抛弃一种方法对其他人有效。我不确定我在这里做错了什么。我对Linq的表达能力建设部分还不熟悉 我的扩展方法如下: void Main() { var people = LoadData().AsQueryable(); var expression = people.PropertySelector<Person>("LastName"); expression.Should().BeOfType(typeof(Express
void Main()
{
var people = LoadData().AsQueryable();
var expression = people.PropertySelector<Person>("LastName");
expression.Should().BeOfType(typeof(Expression<Func<Person, object>>));
var result = people.OrderBy(expression);
}
public static class Extensions
{
public static Expression<Func<T, object>> PropertySelector<T>(this IEnumerable<T> collection, string propertyName)
{
if (string.IsNullOrWhiteSpace(propertyName))
{
throw new ArgumentException(nameof(propertyName));
}
var properties = typeof(T).GetProperties();
if (!properties.Any(p => p.Name == propertyName))
{
throw new ObjectNotFoundException($"Property: {propertyName} not found for type [{typeof(T).Name}]");
}
var propertyInfo = properties.Single(p => p.Name == propertyName);
var alias = Expression.Parameter(typeof(T), "_");
var property = Expression.Property(alias, propertyInfo);
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), propertyInfo.PropertyType);
var lambda = Expression.Lambda(funcType, property, alias);
return (Expression<Func<T, object>>)lambda;
}
}
#region
private Random rand = new Random();
// Define other methods and classes here
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public IEnumerable<Person> LoadData()
{
IList<Person> people = new List<Person>();
for (var i = 0; i < 15; i++)
{
people.Add(new Person
{
FirstName = $"FirstName {i}",
LastName = $"LastName {i}",
Age = rand.Next(1, 100)
});
}
return people;
}
#endregion
我的演员阵容不正确怎么办?谢谢
编辑:
我用我正在玩的完整代码进行了更新。我只是想弄清楚是否有一种简单的方法可以通过传递属性名来生成lambda表达式。我以前做过类似的事情,但我只是在属性名上做了一个切换,然后使用lambda语法动态创建OrderBy查询
这正是我试图学习如何使用表达式静态方法来实现与下面示例相同的结果。我试图通过扩展方法来模拟下面的内容。但不一定要这样。在林帕德闲逛时,这是最容易尝试的
Expression<Func<Loan, object>> sortExpression;
switch (propertyFilter)
{
case "Age":
sortExpression = (l => l.Age);
break;
case "LastName":
sortExpression = (l => l.LastName);
break;
default:
sortExpression = (l => l.FirstName);
break;
}
var sortedLoans = loans.AsQueryable().OrderBy(sortExpression);
sortedLoans.Dump("Filtered Property Result");
Expression-sortExpression;
开关(属性过滤器)
{
案例“年龄”:
sortExpression=(l=>l.Age);
打破
案例“LastName”:
sortExpression=(l=>l.LastName);
打破
违约:
sortExpression=(l=>l.FirstName);
打破
}
var sortedLoans=loans.AsQueryable().OrderBy(sortExpression);
sortedLoans.Dump(“过滤属性结果”);
您的代码正在创建一个Func
,因为您使用
var propertyInfo = properties.Single(p => p.Name == propertyName);
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), propertyInfo.PropertyType);
var-propertyInfo=properties.Single(p=>p.Name==propertyName);
var funcType=typeof(Func).MakeGenericType(typeof(T),propertyInfo.PropertyType);
如果要返回一个
Func
,则创建一个Func
,而不是Func
,否则更好的解决方案是使用Func
并创建一个完全通用的函数。您的代码正在创建一个Func
,因为您使用
var propertyInfo = properties.Single(p => p.Name == propertyName);
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), propertyInfo.PropertyType);
var-propertyInfo=properties.Single(p=>p.Name==propertyName);
var funcType=typeof(Func).MakeGenericType(typeof(T),propertyInfo.PropertyType);
如果要返回
Func
,请创建Func
,而不是Func
,否则更好的解决方案是使用Func
并创建一个完全通用的函数。要保留当前方法签名,可以执行以下操作:
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), typeof(object));
var typeAs = Expression.TypeAs(property, typeof(object));
var lambda = Expression.Lambda(funcType, typeAs, alias);
var funcType=typeof(Func).MakeGenericType(typeof(T),typeof(object));
var typeAs=Expression.typeAs(属性,typeof(对象));
var lambda=Expression.lambda(funcType、typeAs、alias);
更好的方法是将您的方法更改为
public static Expression<Func<T, Tout>> PropertySelector<T, Tout>(this IEnumerable<T> collection, string propertyName)
{
if (string.IsNullOrWhiteSpace(propertyName))
{
throw new ArgumentException(nameof(propertyName));
}
var properties = typeof(T).GetProperties();
if (!properties.Any(p => p.Name == propertyName))
{
throw new ObjectNotFoundException($"Property: {propertyName} not found for type [{typeof(T).Name}]");
}
var propertyInfo = properties.Single(p => p.Name == propertyName);
var alias = Expression.Parameter(typeof(T), "_");
var property = Expression.Property(alias, propertyInfo);
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), propertyInfo.PropertyType);
var lambda = Expression.Lambda(funcType, property, alias);
return (Expression<Func<T, Tout>>)lambda;
}
公共静态表达式属性选择器(此IEnumerable集合,字符串属性名称)
{
if(string.IsNullOrWhiteSpace(propertyName))
{
抛出新的ArgumentException(nameof(propertyName));
}
var properties=typeof(T).GetProperties();
如果(!properties.Any(p=>p.Name==propertyName))
{
抛出新的ObjectNotFoundException($“未找到类型[{typeof(T.Name}]”的属性:{propertyName});
}
var propertyInfo=properties.Single(p=>p.Name==propertyName);
变量别名=表达式参数(typeof(T),“”);
var property=Expression.property(别名,propertyInfo);
var funcType=typeof(Func).MakeGenericType(typeof(T),propertyInfo.PropertyType);
var lambda=Expression.lambda(funcType、属性、别名);
返回(表达式)lambda;
}
并称之为
var expression = people.PropertySelector<Person, string>("LastName");
var expression=people.PropertySelector(“LastName”);
要保留当前方法签名,可以执行以下操作:
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), typeof(object));
var typeAs = Expression.TypeAs(property, typeof(object));
var lambda = Expression.Lambda(funcType, typeAs, alias);
var funcType=typeof(Func).MakeGenericType(typeof(T),typeof(object));
var typeAs=Expression.typeAs(属性,typeof(对象));
var lambda=Expression.lambda(funcType、typeAs、alias);
更好的方法是将您的方法更改为
public static Expression<Func<T, Tout>> PropertySelector<T, Tout>(this IEnumerable<T> collection, string propertyName)
{
if (string.IsNullOrWhiteSpace(propertyName))
{
throw new ArgumentException(nameof(propertyName));
}
var properties = typeof(T).GetProperties();
if (!properties.Any(p => p.Name == propertyName))
{
throw new ObjectNotFoundException($"Property: {propertyName} not found for type [{typeof(T).Name}]");
}
var propertyInfo = properties.Single(p => p.Name == propertyName);
var alias = Expression.Parameter(typeof(T), "_");
var property = Expression.Property(alias, propertyInfo);
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), propertyInfo.PropertyType);
var lambda = Expression.Lambda(funcType, property, alias);
return (Expression<Func<T, Tout>>)lambda;
}
公共静态表达式属性选择器(此IEnumerable集合,字符串属性名称)
{
if(string.IsNullOrWhiteSpace(propertyName))
{
抛出新的ArgumentException(nameof(propertyName));
}
var properties=typeof(T).GetProperties();
如果(!properties.Any(p=>p.Name==propertyName))
{
抛出新的ObjectNotFoundException($“未找到类型[{typeof(T.Name}]”的属性:{propertyName});
}
var propertyInfo=properties.Single(p=>p.Name==propertyName);
变量别名=表达式参数(typeof(T),“”);
var property=Expression.property(别名,propertyInfo);
var funcType=typeof(Func).MakeGenericType(typeof(T),propertyInfo.PropertyType);
var lambda=Expression.lambda(funcType、属性、别名);
返回(表达式)lambda;
}
并称之为
var expression = people.PropertySelector<Person, string>("LastName");
var expression=people.PropertySelector(“LastName”);
我得到了我想要的结果。在@Gusman、@IvanStoev和@PetSerAl发表评论后,我让它开始工作。我可以继续我的探索和学习了。非常感谢你。最终的结果是模板化Propertytype
public static Expression<Func<T, TPropertyType>> PropertySelector<T, TPropertyType>(this IEnumerable<T> collection, string propertyName)
{
if (string.IsNullOrWhiteSpace(propertyName))
{
throw new ArgumentException(nameof(propertyName));
}
var properties = typeof(T).GetProperties();
if (!properties.Any(p => p.Name == propertyName))
{
throw new ObjectNotFoundException($"Property: {propertyName} not found for type [{typeof(T).Name}]");
}
var propertyInfo = properties.Single(p => p.Name == propertyName);
var alias = Expression.Parameter(typeof(T), "_");
var property = Expression.Property(alias, propertyInfo);
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), typeof(TPropertyType));
var lambda = Expression.Lambda(funcType, property, alias);
return (Expression<Func<T, TPropertyType>>)lambda;
}
公共静态表达式属性选择器(此IEnumerable集合,字符串属性名称)
{
if(string.IsNullOrWhiteSpace(propertyName))
{
抛出新的ArgumentException(nameof(propertyName));
}
var properties=typeof(T).GetProperties();
如果(!properties.Any(p=>p.Name==propertyName))
{
抛出新的ObjectNotFoundException($“未找到类型[{typeof(T.Name}]”的属性:{propertyName});
}
var propertyInfo=properties.Single(p=>p.Name==propertyName);
变量别名=表达式参数(typeof(T),“”);
var property=Expression.property(别名,propertyInfo);
var funcType=typeof(Func)。MakeGenericType(typeof(T),typeof(T