我有动态lambda表达式树,我准备我的表达式并编译它。
我的问题是当我准备类似
的表达式时MyClass1.Property2.ChildProperty1=="xyz";
如果Property2为null,则我将nullrefence错误。
public class MyClass1
{
public string Property1{get;set;}
public MyClass2 Property2{get;set;}
}
public class MyClass2
{
public string ChildProperty1{get;set;}
public string ChildProperty2{get;set;}
}
public Func<T, bool> CompileRule<T>(Rule r)
{
...
Func<T, bool> myfunc =Expression.Lambda<Func<T, bool>>(expr, paramUser).Compile();
...
return myfunc;
}
我执行我的请求的另一个功能,如&#34; MYFUNC(myrequest); &#34;
当我在CompileTime中预表达我的表达式时是否有通用的方法来检查空控制,如果ParentProperty为null然后为这些语句返回false?在编译方法中我没有实体,所以我必须准备带有check null控件的语句
答案 0 :(得分:2)
所以你想动态创建一个表达式的主体:
Expression<Func<MyClass1, string>> expr =
x => x.Property2?.ChildProperty1;
不幸的是,目前还没有支持这种标准的Expression
方法。如果您尝试以上操作,则会出现编译时错误:
错误CS8072表达式树lambda可能不包含空传播运算符。
一种可能的方法是生成这样的表达式的主体:
Expression<Func<MyClass1, string>> expr =
x => x.Property2 != null ? x.Property2.ChildProperty1 : null;
这不是确切的等价物,但应该有效。
以下是动态执行此操作的示例代码段:
string memberPath = ...; // e.g. "Property2.ChildProperty2"
var parameter = Expression.Parameter(typeof(T), "x");
Expression result;
if (memberPath.IndexOf('.') < 0)
result = Expression.PropertyOrField(parameter, memberPath);
else
{
var memberNames = memberPath.Split('.');
var members = new Expression[memberNames.Length];
for (int i = 0; i < memberNames.Length; i++)
members[i] = Expression.PropertyOrField(i > 0 ? members[i - 1] : parameter, memberNames[i]);
result = members[members.Length - 1];
// For non nullable value types, promote the result into the corresponding nullable type
if (result.Type.IsValueType && Nullable.GetUnderlyingType(result.Type) == null)
result = Expression.Convert(result, typeof(Nullable<>).MakeGenericType(result.Type));
var nullResult = Expression.Constant(null, result.Type);
for (int i = members.Length - 2; i >= 0; i--)
{
result = Expression.Condition(
Expression.NotEqual(members[i], Expression.Constant(null)),
result, nullResult);
}
}
最后,result
变量包含可用于比较谓词左侧的表达式。