【问题标题】:Reflection to Filter List<T>反射到过滤器列表<T>
【发布时间】:2014-01-01 09:59:22
【问题描述】:

我是 Reflection 的新手,所以请原谅我的菜鸟问题。如何创建一个采用两个参数、一个通用列表和一个字符串的方法,然后在该列表中找到任何属性值与字符串匹配的所有项目。

例如,我们有一个具有 3 个属性的对象,我将这个对象的列表传递给方法和一个搜索字符串,然后它返回一个对象列表,其中任何属性都可能包含搜索字符串。

我可以这样做:

var temp = list.AsQueryable().Where("SomeField == 1").Select("it");

但是我怎样才能使这个方法通用,以便我可以将任何对象列表传递给它?

提前谢谢...

【问题讨论】:

  • 为什么要这样做?这是一件很奇怪的事情,也许有更好的方法来做。
  • 我正在为 jTable 构建一个过滤器,我可以在其中输入文本并根据文本过滤网格。 jTable 使用对象列表。我想构建一个通用方法,这样我就可以一遍又一遍地使用它。

标签: c# .net generics reflection asqueryable


【解决方案1】:

如果你使用的是 Dynamic Linq,试试这个

public static IEnumerable<T> Filter<T>(IEnumerable<T> source, string searchStr)
{
    var propsToCheck = typeof (T).GetProperties().Where(a => a.PropertyType == typeof(string));

    var filter = propsToCheck.Aggregate(string.Empty, (s, p) => (s == string.Empty ? string.Empty : string.Format("{0} OR ", s)) + string.Format("{0} == @0", p.Name));

    var filtered = source.AsQueryable().Where(filter, searchStr);
    return filtered;
}

【讨论】:

  • 太棒了,如何扩展它以允许 .Contains 扩展名?因此,我可以只打开包含字符串的对象,而不是 100% 匹配?
  • 只需将“{0} == @0”更改为“{0}.Contains(@0)”,但您应该检查是否为空,因此如果某些属性可能为空,请使用“{ 0} != null && {0}.Contains(@0)"
【解决方案2】:

使用Type.GetProperties() 获取对象的所有属性。使用PropertyInfo.GetValue() 获取给定对象中给定属性的值。您需要弄清楚如何将字符串与 DateTime、数字或其他复杂对象进行匹配。将其全部放入像bool IsMatch(this object obj, string val) 这样的函数中。然后你可以过滤你的列表,比如list.Where(x =&gt; x.IsMatch("something"))

【讨论】:

  • 你能给我一个示例方法吗?
  • 我已经为您提供了使其工作所需的所有信息,但显然其他人更迫切需要积分:)。
  • 我认为这里的重点不是吹嘘理论知识。说一个列表并过滤它很容易。其他人可能是为了 SOF 的精神,给一个答案,如果不是这样,为什么要使用 SOF ?无论如何,所有答案都可以在 Local Barnes and Noble 获得,对吗?
  • 我没有吹牛,我没有给出理论上的答案。我给了你确切的细节,你需要调用哪些方法来实现你的目标。你问how,我给你how。你不能指望 SO 的精神是人们代替你做你的工作。有些人有时会编写实际的源代码,但这是一项额外的服务。
  • 我和@fejesjoco 在一起。在得到答案时,有些人可能会解释如何做,如果可能的话,有些人可能会提供完整的答案和工作代码。你不能要求有人为你做所有事情。它们都是答案。
【解决方案3】:

你来了,伙计:

    private static void Main(string[] args)
    {
        var list = new List<object> {new {prop1 = "A", prop2 = "B"},new {prop3 = "B", prop4 = "C"}};
        var subList = SearchForStringInProperties(list, "C");
    }

    private static IEnumerable<object> SearchForStringInProperties(IEnumerable<object> list, string searchString)
    {
        return from obj in list where FindStringInObjProperties(obj, searchString) select obj;
    }

    private static bool FindStringInObjProperties(object obj, string searchString)
    {
        return obj.GetType().GetProperties().Any(property => obj.GetType().GetProperty(property.Name).GetValue(obj).ToString().Equals(searchString));
    }

【讨论】:

  • 如果 prop1 为空怎么办?
  • 好点,而且很好发现,但这是显示概念的示例代码,而不是生产就绪代码。当然,您也可以轻松检查 null 。感谢您指出这一点。
  • 谢谢老兄,我从来没想过这样做...谢谢教育
【解决方案4】:

如果您只想匹配与参数相同类型的属性,此扩展方法可以提供帮助,

 public static class ListExtensions
{
    public static IEnumerable<T> MatchWithAnyProperty<T, TK>(this IEnumerable<T> list, TK value)
    {
        var argType = typeof (TK);
        var properties = typeof(T).GetProperties().Where(x => x.PropertyType.IsAssignableFrom(argType));

      return  list.Where(item => properties.Any(prop =>
            {
                var propertyValue = prop.GetValue(item, null);
                if (value == null)
                    return propertyValue == null;
                return propertyValue.Equals(value);
            }));
    }
}

这可以像这样使用,

var items = new[]
            {
                new
                    {
                        Name = "Test",
                        Age = 20,
                        Test=25
                    },
                new
                    {
                        Name = "Hello",
                        Age = 10,
                        Test=15
                    },
                new
                    {
                        Name = "T2gdhest",
                        Age = 14,
                        Test=20
                    },
                new
                    {
                        Name = "hai",
                        Age = 33,
                        Test=10
                    },
                new
                    {
                        Name = "why not",
                        Age = 10,
                        Test=33
                    },
            };

       var match= items.MatchWithAnyProperty(10);

        foreach (var item in match)
        {
            Console.WriteLine(item.Name);
        }
        Console.ReadKey();

【讨论】:

  • Mathew,我试过了,它可以像广告一样工作,除非属性值为 null。
【解决方案5】:

还有老办法……

    public static IList<T> MyMethod<T>(IList<T> myList, string filter)
    {
        if (myList == null) return null;
        if (filter == null) return myList;

        var tfilter = filter.GetType();
        var properties = typeof(T).GetProperties().Where(x => x.PropertyType.FullName == typeof(string).FullName);
        if (!properties.Any()) return null;


        var res = new List<T>();

        foreach(var el in myList)
        {
            foreach(var p in properties)
            {
                if ((string)p.GetValue(el) == filter)
                {
                    res.Add(el);
                    break;
                }
            }
        }
        return res;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 2022-01-08
    • 2012-11-20
    • 1970-01-01
    • 2019-03-14
    • 2023-02-22
    • 2017-01-17
    相关资源
    最近更新 更多