构建lambda表达式以过滤字典列表中的内容

时间:2019-05-19 16:29:39

标签: c# linq dictionary filtering

所以,大家好!

我有下一堂课

public class ExportItem
    {
        public Dictionary<string, object> Container { get; set; }

        public ExportItem()
        {
            Container = new Dictionary<string, object>();
        }
    }

在我的情况下,Container包含一组成对的“属性名称-此属性的值”。

接下来,我有List<ExportItem>

问题是,我想使用(我认为是最好的方法)动态构建的表达式来筛选此列表。

当我拥有带有属性的传统类时,我知道如何为这种情况构建简单的表达式:

var parameter = Expression.Parameter(typeof(People), property);
var member = Expression.Property(parameter, "Id"); //x.Id
var constant = Expression.Constant(3);
var body = Expression.GreaterThanOrEqual(member, constant); //x.Id >= 3
var finalExpression = Expression.Lambda<Func<People, bool>>(body, parameter); //x => x.Id >= 3   

但是对于我来说,我不应该通过属性Id进行过滤,而应该通过收集字典的值进行过滤。

即我必须只接受那些ExportItem's,其中Container我具有名称(键)的属性,例如,“年龄”和大于“ 12”的值。 (我可以轻松地将字典的值转换为字符串并比较这些字符串-在这种情况下,它并不是那么重要)。

我想知道这是否有可能。如果是这样,请指导我如何创建正确的表达式,否则,也许您可​​以提供更好的方法来创建我的过滤器?

1 个答案:

答案 0 :(得分:0)

我会这样写:

class Program {

    static void Main(string[] args) {
        //Initialize scenario
        var item1 = new ExportItem();
        var item2 = new ExportItem();
        var item3 = new ExportItem();
        item1.Container["ID"] = Guid.NewGuid();
        item1.Container["Name"] = "John Smith";
        item1.Container["DateOfBirth"] = new DateTime(2002, 10, 10);
        item2.Container["Name"] = "Alice";
        item2.Container["DateOfBirth"] = new DateTime(2004, 10, 20);
        item2.Container["ID"] = Guid.NewGuid();
        item3.Container["ID"] = Guid.NewGuid();
        item3.Container["Name"] = "Bob";
        item3.Container["DateOfBirth"] = "Invalid Date";
        List<ExportItem> myExportItems = new List<ExportItem>() { item1, item2, item3 };
        //Initialize filter (older than 12 years)
        Int32 myAge = 12;
        DateTime myAgeLimit = DateTime.Today.AddYears(myAge * -1);
        Predicate<KeyValuePair<String, Object>> myFilter = (x => (x.Key == "DateOfBirth") && (x.Value is DateTime) && ((DateTime)x.Value) < myAgeLimit);
        //Filter the according items
        var myResult = (from e in myExportItems from e2 in e.Container where myFilter(e2) select e);
        //Execute something 
        Console.Out.WriteLine($"Older than {myAge} years old:");
        foreach (var myExportItem in myResult) {
            var myContainer = myExportItem.Container;
            String myID = "unknown";
            String myName = "unknown";
            String myDateOfBirth = ((DateTime)myContainer["DateOfBirth"]).ToString("yyyy-MM-dd");
            try {
                myID = ((Guid)myContainer["ID"]).ToString("D");
            } catch { }
            try {
                myName = ((String)myContainer["Name"]);
            } catch { }
            Console.WriteLine($"myID={myID}");
            Console.WriteLine($"myID={myName}");
            Console.WriteLine($"myID={myDateOfBirth}");
            Console.WriteLine();
        }

    }

}

public class ExportItem {

    public Dictionary<string, object> Container { get; set; }

    public ExportItem() {
        Container = new Dictionary<string, object>();
    }

}

PS:保存年龄是邪恶的。而是存储生日。