C# 使用检查parentproperty null控件准备动态Lambda表达式

C# 使用检查parentproperty null控件准备动态Lambda表达式,c#,linq,lambda,expression,C#,Linq,Lambda,Expression,我有一个动态lambda表达式树,我准备我的表达式并编译它 我的问题是当我准备表达的时候 MyClass1.Property2.ChildProperty1=="xyz"; 如果Property2为null,则取nullrefence错误 public class MyClass1 { public string Property1{get;set;} public MyClass2 Property2{get;set;} } public class MyClass2 {

我有一个动态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;
}
公共类MyClass1
{
公共字符串属性1{get;set;}
公共MyClass2属性2{get;set;}
}
公共类MyClass2
{
公共字符串ChildProperty1{get;set;}
公共字符串ChildProperty2{get;set;}
}
公共函数编译器(规则r)
{
...
Func myfunc=Expression.Lambda(expr,paramUser).Compile();
...
返回myfunc;
}
我执行请求的另一个函数,如“myfunc(myrequest);”


当我在CompileTime中输入表达式时,是否有一种检查null控件的通用方法,如果ParentProperty为null,则为这些语句返回false?在compile方法中,我没有实体,因此我必须使用check null control来准备语句,所以您希望动态创建一个表达式体,如下所示:

Expression<Func<MyClass1, string>> expr = 
    x => x.Property2?.ChildProperty1;
这不是完全等效的,但应该有效

下面是一个示例代码段,它动态地执行此操作:

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);
    }
}
string memberPath=…;//e、 g.“财产2.儿童财产2”
var参数=表达式参数(类型为(T),“x”);
表达结果;
if(memberPath.IndexOf('.')<0)
结果=Expression.PropertyOrField(参数,memberPath);
其他的
{
var memberNames=memberPath.Split('.');
var members=新表达式[memberNames.Length];
for(int i=0;i0?members[i-1]:参数,memberNames[i]);
结果=成员[members.Length-1];
//对于不可为null的值类型,将结果升级为相应的可为null的类型
if(result.Type.IsValueType&&null.getUnderlinegType(result.Type)==null)
result=Expression.Convert(result,typeof(Nullable).MakeGenericType(result.Type));
var nullResult=Expression.Constant(null,result.Type);
对于(int i=members.Length-2;i>=0;i--)
{
结果=表达式。条件(
Expression.NotEqual(成员[i],Expression.Constant(null)),
结果,结果),;
}
}

最后,
result
变量包含可用于比较谓词左侧的表达式。

不太清楚您在问什么,但可以使用C#6中的null条件运算符:
MyClass1?.Property2?.ChildProperty==“xyz”
。如果
MyClass1
为null,或者
MyClass1.Property2
为null,则返回false。这就是你想要的吗?是的,我想这样做,但是我动态地准备这个语句。有没有一种通用的方法来准备我的表达式,比如。expression.Constant(r.TargetValue,typeof(string))和expression.Equal(expression.Property(parameter,item.Key),expression.Constant(item.Value))@j0ey_wh:您没有格式化代码-您取消了我上次编辑的格式化。根本不清楚
r.TargetValue
参数
项.Key
项.Value
是什么。从代码的早期开始,看起来您使用的是lambda表达式,但现在听起来好像不是。我们无法真正帮助你,因为我们不得不猜测你想要实现什么。请将其编辑成一个。我在运行时创建动态lambda表达式,并编译它,然后执行。如果父属性为null,则我希望在表达式中添加null检查,而不是在父属性为null时我接受null引用错误。当我准备表达式时,我使用c#lambda方法,如expression.Equal,Expression.constant类似于Expression.MakeBinary(tBinary,propExpression,right)作为结果{(Param_0.Body.No==6)},我如何与这些表达式组合。我尝试了一下,但得到了二进制运算符,并且也没有为类型“System.Nullable`1[System.Int32]”和“System.Boolean”定义。var a=AccessMember(r.MemberName,paramExp);var b=Expression.MakeBinary(tBinary,propExpression,right),Expression.AndAlso(a,b);您可能需要将
right
转换为
left
的类型。例如
if(right.type!=left.type)right=Expression.convert(right,left.type)
I转换但仍然得到二进制运算符,并且没有为类型“System.Nullable
1[System.Int32]”和“System.Nullable
1[System.Int32]”定义错误它们不应该是
int
(或
Nullable
)表达式类型。
AndAlso
需要
bool
表达式。在您的示例中,
a
应该是
left
,如果
right
转换为
left
类型,
var b=expression.MakeBinary(tBinary,left,right),
应该是
bool
类型。如果你发布完整的代码,我可以看一下。
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);
    }
}