鉴于以下类
public class ClassA
{
public string StringProperty { get; set; }
public List<ClassB> List { get; set; }
}
public class ClassB
{
public int IntProperty { get; set; }
}
我想动态创建一个如下所示的表达式
x => x.StringProperty == "X" && x.List.Any( y => y.IntProperty > 1 )
第一部分没问题(x.StringProperty == "X"
)。对于第二部分,我创建了一个对应的成员表达式x.List
,现在需要
y
实际上是相同的内部类型x.List
关于第一点的任何提示?我如何获得 an 的类型 T IEnumerable<T>
?
编辑
我已尝试使用以下代码,但不幸的是它返回 null
//This expression will be x.List of my original sample
MemberExpression expr = GetMemberExpression( property, pe );
Type innerType = expr.GetType()
.GetInterfaces()
.Where( t => t.IsGenericType == true && t.GetGenericTypeDefinition() == typeof( IEnumerable<> ) )
.Select( t => t.GetGenericArguments()[0] )
.SingleOrDefault();
给定的
private static readonly MethodInfo anyT = (from x in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static)
where x.Name == nameof(Enumerable.Any) && x.IsGenericMethod
let gens = x.GetGenericArguments()
where gens.Length == 1
let pars = x.GetParameters()
where pars.Length == 2 &&
pars[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(gens[0]) &&
pars[1].ParameterType == typeof(Func<,>).MakeGenericType(gens[0], typeof(bool))
select x).Single();
// https://stackoverflow.com/a/906513/613130
private static IEnumerable<Type> GetGenericIEnumerables(Type type)
{
return type.GetInterfaces()
.Where(t => t.IsGenericType == true
&& t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.Select(t => t.GetGenericArguments()[0]);
}
那么你就可以:
var parX = Expression.Parameter(typeof(ClassA), "x");
var list = Expression.Property(parX, nameof(ClassA.List));
var listType = list.Type;
var baseType = GetGenericIEnumerables(listType).First();
var parY = Expression.Parameter(baseType, "y");
var eq = Expression.Equal(
Expression.Property(parX, nameof(ClassA.StringProperty)),
Expression.Constant("X"));
var gt = Expression.GreaterThan(
Expression.Property(parY, "IntProperty"),
Expression.Constant(1));
var innerExpression = Expression.Lambda(gt, parY);
var any = Expression.Call(
anyT.MakeGenericMethod(baseType),
list,
innerExpression);
var and = Expression.AndAlso(eq, any);
var outerExpression = Expression.Lambda<Func<ClassA, bool>>(and, parX);
var compiled = outerExpression.Compile();
var result = objs.Where(compiled).ToArray();
请注意,您不需要编译innerExpression
:outerExpression.Compile()
将为您做所有事情!
我使用的修改版本自IEnumerable <T>得到类型T找到T
的IEnumerable<T>
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句