0

我想在 NewExpression 中有效地使用空值守卫。我想我最好用例子来解释。

用下面的代码,InstantiateChildClass设置成true输出会是下面这样,就完美了。

{
  "TestProp": "testing testing",
  "Another": "une notre",
  "SomeProp": "test string"
}

我想要实现的是下面代码的以下输出,当InstantiateChildClass设置为false.

{
  "TestProp": "testing testing",
  "Another": "une notre",
  "SomeProp": null
}

这目前不会发生(当然),因为ChildClasssrc.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; }
    }
}
4

0 回答 0