我想在 NewExpression 中有效地使用空值守卫。我想我最好用例子来解释。
用下面的代码,InstantiateChildClass
设置成true
输出会是下面这样,就完美了。
{
"TestProp": "testing testing",
"Another": "une notre",
"SomeProp": "test string"
}
我想要实现的是下面代码的以下输出,当InstantiateChildClass
设置为false
.
{
"TestProp": "testing testing",
"Another": "une notre",
"SomeProp": null
}
这目前不会发生(当然),因为ChildClass
在src.ChildClass.SomeProp
. 如果不使用表达式来编写它,它会像src.ChildClass?.SomeProp
. 然而,对于表达式,这是不可能的(还没有?),所以NullReferenceExpception
会出现 a。
我玩了几个小时,但我似乎无处可去。除了需要工作代码之外,我真的很想了解如何使用表达式来做到这一点,因为目前它们对我来说仍然有点神奇。我最初通过将编译的方法包装在 try catch 中并在NullReferenceException
. 但是,此代码用于转换数千个对象,并且在使用 try catch '解决方案'时表现不佳。
代码:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace ExpressionTest
{
class Program
{
private static bool InstantiateChildClass = true;
static void Main(string[] args)
{
var func = Test<TestClass, object>(src => new { src.TestProp, src.Another, src.ChildClass.SomeProp, });
var testClass = new TestClass
{
Another = "une notre",
TestProp = "testing testing"
};
if (InstantiateChildClass)
{
testClass.ChildClass = new SomeClass
{
SomeProp = "test string"
};
}
try
{
var outcome = func(testClass);
var json = Newtonsoft.Json.JsonConvert.SerializeObject(outcome, Formatting.Indented);
Console.WriteLine(json);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
private static Func<TIn, TOut> Test<TIn, TOut>(Expression<Func<TIn, TOut>> expression)
{
var newExpression = expression.Body as NewExpression;
#region With what I have been playing... unsuccessfully.
int argCounter = 0;
var exprs = new List<Expression>();
foreach (var arg in newExpression.Arguments)
{
var memberStringExpression = arg.ToString();
var parts = memberStringExpression.Split(".");
var memberExpression = arg as MemberExpression;
if (parts.Length > 2)
{
//var constExpr = Expression.Constant("const expr");
//var propertyInfo = memberExpression.Member as PropertyInfo;
//var paramExpr = Expression.Parameter(propertyInfo.PropertyType, "ExprPop");
//var assignExpression = Expression.Assign(paramExpr, constExpr);
//var memberExpression = Expression.Property(assignExpression, "ValueFromExpr");
exprs.Add(memberExpression);
}
else
{
exprs.Add(arg);
}
argCounter++;
}
newExpression.Update(exprs);
#endregion
return expression.Compile();
}
}
public class TestClass
{
public string TestProp { get; set; }
public string Another { get; set; }
public SomeClass ChildClass { get; set; }
}
public class SomeClass
{
public string SomeProp { get; set; }
}
}