反映过滤清单<t> </t>

时间:2013-12-13 15:14:20

标签: c# .net generics reflection asqueryable

我是反思的新手,请原谅我的noob问题。如何创建一个带有两个参数的方法,一个通用列表和一个字符串,然后查找该列表中任何属性值与字符串匹配的所有项目。

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

我可以这样做:

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

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

提前致谢...

5 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

你在这里交配:

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

答案 2 :(得分: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;
}

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

还有旧方法......

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