假设您有一个通用类,它有一个 List<T> Items;
现在想想这个基本的 lambda 表达式:
var result = Items.FindAll(x => x.Name = "Filip");
这只有在我们知道 T
的属性时才有效,当它是泛型类型时你不会这样做。
因此我想像这样使用反射获取属性:
PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public);
并以某种方式将其与上述 Lambda 表达式结合,以便它搜索 Type 的所有公共(public)属性并查看它是否包含“Filip”,此时我不关心属性名称是否为 Name。
这可能吗?
最佳答案
var result = Items.FindAll(x =>
properties.Any(p => p.PropertyType == typeof(string) &&
p.GetValue(x, null) == "Filip"));
显然,这是一个简单的、乐观的字符串比较(例如,您可能想使用 string.Compare
),但这应该使思路清晰。
编辑
dtb 在使用表达式树方面提出了一个很好的建议。你可以像这样以更快的方式完成你想要的:
public static class PropertyScanner
{
static Func<TType, bool> CreatePredicate<TType, TValue>(TValue value, IEqualityComparer<TValue> comparer)
{
var arg = Expression.Parameter(typeof(TType), "arg");
Expression body = null;
Expression<Func<TValue, TValue, bool>> compare = (val1, val2) => comparer.Equals(val1, val2);
foreach (PropertyInfo property in typeof(TType).GetProperties(BindingFlags.Public))
{
if (property.PropertyType == typeof(TValue) || typeof(TValue).IsAssignableFrom(property.PropertyType))
{
Expression prop = Expression.Equal(Expression.Invoke(compare, new Expression[]
{
Expression.Constant(value),
Expression.Property(arg, property.Name)
}),
Expression.Constant(0));
if (body == null)
{
body = prop;
}
else
{
body = Expression.OrElse(body, prop);
}
}
}
return Expression.Lambda<Func<TType, bool>>(body, arg).Compile();
}
public static IEnumerable<TType> ScanProperties<TType, TValue>(this IEnumerable<TType> source, TValue value)
{
return ScanProperties<TType, TValue>(source, value, EqualityComparer<TValue>.Default);
}
public static IEnumerable<TType> ScanProperties<TType, TValue>(this IEnumerable<TType> source, TValue value, IEqualityComparer<TValue> comparer)
{
return source.Where(CreatePredicate<TType, TValue>(value, comparer));
}
}
这将允许你做这样的事情:
var result = Items.ScanProperties("Filip").ToList();
关于c# - List<T> 上的 Lambda 并使用反射获取属性名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2133525/