为了账号安全,请及时绑定邮箱和手机立即绑定

在编译表达式之前测试空子

在编译表达式之前测试空子

C#
凤凰求蛊 2022-06-19 10:15:04
我正在尝试通过 检索一个值Expression,但我有一个场景,模型上的子属性为 null 并且我得到一个NullReferenceException.该场景发生在我以以下方式使用模型的情况下,x视图中的模型在哪里并且它不为空,但Contact属性为空:x => x.Contact.Email然后我使用以下方法检索该值:public static FieldInfo Get<TModel, TProperty>(HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression){    object value = null;    if (html.ViewData.Model != null)    {        value = expression.Compile()(html.ViewData.Model);    }    // other code}如何调整此代码以测试子属性上的 null 还是不可能的?
查看完整描述

2 回答

?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

为了在我的IQueryable左外连接实现中处理这个问题,我使用了一个ExpressionVisitor替换null.member为null. 您可以在ExpressionEF/LINQ to SQL 支持的 .


public static class ExpressionExt {

    public static TE AddTestForNull<TE>(this TE orig) where TE : Expression => (TE)(new NullTestVisitor().Visit(orig));

}



/// <summary>

/// ExpressionVisitor to replace a obj.member Expression with a null test ((obj == null) ? null : obj.member)

/// </summary>

public class NullTestVisitor : System.Linq.Expressions.ExpressionVisitor {

    public override Expression Visit(Expression node) {

        if (node is MemberExpression nme)

            return Expression.Condition(Expression.MakeBinary(ExpressionType.Equal, nme.Expression.AddTestForNull(), Expression.Constant(null, nme.Expression.Type)),

                                        Expression.Constant(null, nme.Type),

                                        nme);

        else

            return base.Visit(node);

    }

}

然后,当您需要处理此类问题时Expression,只需继续AddTestForNull:


value = expression.AddTestForNull().Compile()(html.ViewData.Model);

这将在每个级别添加测试 - 如果您有x => x.member.testMember,它将被替换为((x == null ? null : x.member) == null ? null : x.member.testMember).


查看完整回答
反对 回复 2022-06-19
?
Helenr

TA贡献1780条经验 获得超4个赞

您是否可以调整 Get(..) 方法以使用 Func 而不是表达式?


表达式不允许 Null Coalescing 或 Null Propagation 运算符。但是函数可以。


//Yours

public static FieldInfo Get<TModel, TProperty>(HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) { ... }


//Potential solution for you

public static FieldInfo Get<TModel, TProperty>(HtmlHelper<TModel> person, Func<TModel, TProperty> func) { ... }

表达式不允许 Null Coalescing 或 Null Propagation 运算符。但是函数可以。


请原谅类型的差异。我正在使用我当时最容易获得的东西来为你创建一个具体的例子。


请注意,调用的是 Invoke() 方法而不是 Compile()


public static object Get<Person, TProperty>(Person person, Func<Person, TProperty> func)

{

    object result = null;


    if (person != null)

    {

        result = func.Invoke(person);

    }


    return result;

}

示例使用

var personNoContact = new Person { Contact = null };

var result = Get(personNoContact, x => x.Contact?.Email.EmailAddress ?? "");

以下类用于测试

public class Person

{

    public Contact Contact { get; set; }

}


public class Contact

{

    public Email Email { get; set; }

}


public class Email { public string EmailAddress { get; set; } }


查看完整回答
反对 回复 2022-06-19
  • 2 回答
  • 0 关注
  • 111 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信