我是反射区的新手。我必须使用它的键和值来过滤具有字典的实体列表,如下所示
public class Person
{
public string Name { get; set; }
public Dictionary<string,string> SecQuestions { get; set; }
}
以下扩展名在dll中可用,无法修改
public static class extensions
{
public static List<Person> FilterMe(this List<Person> Persons, Func<Person,bool> predicate)
{
// Logic to filter the persion list
return Persons;
}
}
因此我必须使用下面的代码
来调用上面的方法persons.FilterMe(xy => xy.SecQuestions.Any(x => x.Key == "PlaceOfBirth" && x.Value == "Madurai"));
我需要知道如何创建
xy => xy.SecQuestions
.Any(x => x.Key == "PlaceOfBirth" && x.Value == "Madurai")
动态地使用表达式构建器作为参数传递给扩展方法。感谢
答案 0 :(得分:1)
var personP = Expression.Parameter(typeof(Person), "xy"); // Creates xy Parameter
var SecQuestionsProp = Expression.Property(personP, "SecQuestions"); // Creates xy.SecQuestions
var anyMethodInfo = typeof(Enumerable).GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
.Where(m => m.Name == "Any" && m.IsGenericMethod) // Search for Any methods...
.Select(m => new {
Method = m,
Params = m.GetParameters(),
Args = m.GetGenericArguments()
})
.Where(x => x.Args.Length == 1
&& x.Params.Length == 2
&& x.Params[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(x.Args)
&& x.Params[1].ParameterType == typeof(Func<,>).MakeGenericType(new Type[] { x.Args.First(), typeof(bool) })) // Get the one defined as Any<TSource>(IEnumerable<TSource>, Func<TSource, bool>)
.Select(x => x.Method)
.First();
var keyValuePairP = Expression.Parameter(typeof(KeyValuePair<string, string>), "x"); // Creates x Parameter
var KeyProp = Expression.Property(keyValuePairP, "Key"); // Creates x.Key
var keyComparisonValue = Expression.Constant("PlaceOfBirth"); // Creates the value that will be compared to x.Key
var keyComparison = Expression.Equal(KeyProp, keyComparisonValue); // Creates the comparison (x.Key == "PlaceOfBirth")
var ValueProp = Expression.Property(keyValuePairP, "Value"); // Creates x.Value
var valueComparisonValue = Expression.Constant("Madurai"); // Creates the value that will be compared to x.Value
var valueComparison = Expression.Equal(ValueProp, valueComparisonValue); // Creates the comparison (x.Value == "Madurai")
var anyPredicate = Expression.Lambda(Expression.AndAlso(keyComparison, valueComparison), new ParameterExpression[] { keyValuePairP }); // Creates x => x.Key == "PlaceOfBirth" && x.Value == "Madurai"
var filterMeMethod = Expression.Lambda<Func<Person, bool>>
(Expression.Call(anyMethodInfo.MakeGenericMethod(new Type[] { typeof(KeyValuePair<string, string>) })
, new Expression[] { SecQuestionsProp, anyPredicate })
, personP); //Creates xy => xy.SecQuestions.Any(x => x.Key == "PlaceOfBirth" && x.Value == "Madurai")
var r1 = persons.FilterMe(filterMeMethod.Compile()); // Calls FilterMe with xy => xy.SecQuestions.Any(x => x.Key == "PlaceOfBirth" && x.Value == "Madurai") as parameter
答案 1 :(得分:0)
在这里似乎没有任何需要使用表达式构建器,或者实际上任何扩展方法(看起来你正在重新发明轮子)。以下内容应符合您的需求:
var filteredPeople = people.Where(person => person.SecQuestions[key] == value);
key
和value
如何确定取决于您。它可以是方法参数或用户输入等等。
答案 2 :(得分:0)
如果您只需要您要比较的值是动态的,那么您可以让语言变得繁重:
public Expression BuildComparison(string key, string value)
{
return Expression<Func<Person, bool>> exp =
x => x.SecQuestions.Any(y => y.Key == key && y.Value == value);
}
如果我误解了你的要求,请道歉。