列表上的Lambda并使用反射来获取属性名称

发布于 2024-08-19 06:32:36 字数 452 浏览 3 评论 0原文

假设您有一个通用类,其中有一个 List; Items;

现在考虑这个基本的 lambda 表达式:

var result = Items.FindAll(x => x.Name = "Filip");

只要我们知道,这才有效T 的属性,当它是泛型类型时,您不需要这些属性。

因此,我想使用反射来获取属性,如下所示:

PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public);

并以某种方式将其与上面的 Lambda 表达式结合起来,以便它搜索Type的所有公共属性,看看是否包含“Filip”,此时我不在乎property-name是否为Name。

这可能吗?

Let's say you have a Generic Class which have a List<T> Items;

Now think of this basic lambda expression:

var result = Items.FindAll(x => x.Name = "Filip");

This will only work as long as we Know the Properties of T, which you don't when it's a generic type.

Therefore I would like to fetch the properties using Reflection like this:

PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public);

and somehow combind that with the above Lambda-expression so that it searches All the public properties of the Type and see if it contains "Filip", at this time I do not care if the property-name is Name or not.

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鹿! 2024-08-26 06:32:36
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();
var result = Items.FindAll(x => 
    properties.Any(p => p.PropertyType == typeof(string) && 
                        p.GetValue(x, null) == "Filip"));

Obviously this is a simplistic, optimistic string comparison (you might want to use string.Compare, for example), but this should make the idea clear.

Edit

dtb makes a good suggestion in using expression trees. You could accomplish what you're after in a faster fashion like this:

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));
    }
}

This will allow you to do something like this:

var result = Items.ScanProperties("Filip").ToList();
度的依靠╰つ 2024-08-26 06:32:36

您可以使用表达式树即时构建 lambda:

Func<T, bool> CreatePredicate<T>()
{
    var arg = Expression.Parameter(typeof(T), "arg");
    var body = Expression.Equal(Expression.Property(arg, "Name"),
                                Expression.Constant("Filip"));
    return Expression.Lambda<Func<T, bool>>(body, arg).Compile();
}

IEnumerable<T> GetTWhereNameIsFilip<T>(IEnumerable<T> source)
{
    Func<T, bool> predicate = CreatePredicate<T>();
    // cache predicate for max performance

    return source.Where(predicate);
}

You can use expression trees to construct a lambda on-the-fly:

Func<T, bool> CreatePredicate<T>()
{
    var arg = Expression.Parameter(typeof(T), "arg");
    var body = Expression.Equal(Expression.Property(arg, "Name"),
                                Expression.Constant("Filip"));
    return Expression.Lambda<Func<T, bool>>(body, arg).Compile();
}

IEnumerable<T> GetTWhereNameIsFilip<T>(IEnumerable<T> source)
{
    Func<T, bool> predicate = CreatePredicate<T>();
    // cache predicate for max performance

    return source.Where(predicate);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文