Expression.MethodCallExpression 传递 MemberExpression 作为参数
Expression.MethodCallExpression pass MemberExpression as Parameter
我正在尝试通过
上的方法调用来创建通用表达式
Enumerable.Contains
所以基本上我想实现这个简单的 lambda
x => collection.Contains(x.SomeProperty)
到目前为止,我的代码如下所示:
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x");
MemberExpression memberExpression = Expression.Property(parameterExpression, propertyName);
MethodCallExpression methodCall = Expression.Call(
typeof(Enumerable),
"Contains",
new Type[] { typeof(Object) },
Expression.Constant(new Object[] { 1, 2, 3 }),
memberExpression
);
但随后它转储
InvalidOperationException: No generic method 'Contains' on type 'System.Linq.Enumerable' is compatible with the supplied type
arguments and arguments. No type arguments should be provided if the
method is non-generic
如果我只传递 paramterExpression 它工作正常,但这不是我想要的。
我的问题是现在。有没有办法将 Memberexpression 传递给 Contains 方法调用?
这取决于 memberExpression
的 Type
,而 Type
又取决于所访问的 属性 的类型。
例如以下作品:
void Main()
{
string propertyName = "ObjectProperty";
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x");
MemberExpression memberExpression = Expression.Property(parameterExpression, propertyName);
MethodCallExpression methodCall = Expression.Call(
typeof(Enumerable),
"Contains",
new Type[] { typeof(object) },
Expression.Constant(new Object[] { 1, 2, 3 }),
memberExpression
);
Console.WriteLine(Expression.Lambda<Func<T, bool>>(methodCall, parameterExpression).Compile()(new T()));
}
public class T
{
public object ObjectProperty => 2;
public int IntProperty => 4;
}
以下没有:
void Main()
{
string propertyName = "IntProperty";
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x");
MemberExpression memberExpression = Expression.Property(parameterExpression, propertyName);
MethodCallExpression methodCall = Expression.Call(
typeof(Enumerable),
"Contains",
new Type[] { typeof(object) },
Expression.Constant(new Object[] { 1, 2, 3 }),
memberExpression
);
Console.WriteLine(Expression.Lambda<Func<T, bool>>(methodCall, parameterExpression).Compile()(new T()));
}
public class T
{
public object ObjectProperty => 2;
public int IntProperty => 4;
}
您可以使用 new Type[] { memberExpression.Type }
而不是 new Type[] { typeof(object) }
让代码适应 属性 的类型,尽管您还需要参数表达式的类型(在本例中为 Constant(new Object[] {...}
))匹配。
请注意,只有当它们是从相关类型 (object
) 派生的引用类型时,您才能在此处进行隐式转换,因此 属性 返回 string
或 Uri
会很好(尽管在检查它是否包含在 1, 2, 3
数组中时显然总是错误的)但是返回 int
的 属性 不是装箱转换, 不是参考向上转换。
我正在尝试通过
上的方法调用来创建通用表达式Enumerable.Contains
所以基本上我想实现这个简单的 lambda
x => collection.Contains(x.SomeProperty)
到目前为止,我的代码如下所示:
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x");
MemberExpression memberExpression = Expression.Property(parameterExpression, propertyName);
MethodCallExpression methodCall = Expression.Call(
typeof(Enumerable),
"Contains",
new Type[] { typeof(Object) },
Expression.Constant(new Object[] { 1, 2, 3 }),
memberExpression
);
但随后它转储
InvalidOperationException: No generic method 'Contains' on type 'System.Linq.Enumerable' is compatible with the supplied type
arguments and arguments. No type arguments should be provided if the
method is non-generic
如果我只传递 paramterExpression 它工作正常,但这不是我想要的。
我的问题是现在。有没有办法将 Memberexpression 传递给 Contains 方法调用?
这取决于 memberExpression
的 Type
,而 Type
又取决于所访问的 属性 的类型。
例如以下作品:
void Main()
{
string propertyName = "ObjectProperty";
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x");
MemberExpression memberExpression = Expression.Property(parameterExpression, propertyName);
MethodCallExpression methodCall = Expression.Call(
typeof(Enumerable),
"Contains",
new Type[] { typeof(object) },
Expression.Constant(new Object[] { 1, 2, 3 }),
memberExpression
);
Console.WriteLine(Expression.Lambda<Func<T, bool>>(methodCall, parameterExpression).Compile()(new T()));
}
public class T
{
public object ObjectProperty => 2;
public int IntProperty => 4;
}
以下没有:
void Main()
{
string propertyName = "IntProperty";
ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x");
MemberExpression memberExpression = Expression.Property(parameterExpression, propertyName);
MethodCallExpression methodCall = Expression.Call(
typeof(Enumerable),
"Contains",
new Type[] { typeof(object) },
Expression.Constant(new Object[] { 1, 2, 3 }),
memberExpression
);
Console.WriteLine(Expression.Lambda<Func<T, bool>>(methodCall, parameterExpression).Compile()(new T()));
}
public class T
{
public object ObjectProperty => 2;
public int IntProperty => 4;
}
您可以使用 new Type[] { memberExpression.Type }
而不是 new Type[] { typeof(object) }
让代码适应 属性 的类型,尽管您还需要参数表达式的类型(在本例中为 Constant(new Object[] {...}
))匹配。
请注意,只有当它们是从相关类型 (object
) 派生的引用类型时,您才能在此处进行隐式转换,因此 属性 返回 string
或 Uri
会很好(尽管在检查它是否包含在 1, 2, 3
数组中时显然总是错误的)但是返回 int
的 属性 不是装箱转换, 不是参考向上转换。