3

Expressionこのコードを使用して単純なマッパーを作成しようとしています:

public static class MyUtility {

    public static Action<TSource, TTarget> BuildMapAction<TSource, TTarget>(IEnumerable<PropertyMap> properties) {

        var sourceInstance = Expression.Parameter(typeof(TSource), "source");
        var targetInstance = Expression.Parameter(typeof(TTarget), "target");

        var statements = BuildPropertyGettersSetters(sourceInstance, targetInstance, properties);

        Expression blockExp = Expression.Block(new[] { sourceInstance, targetInstance }, statements);

        if (blockExp.CanReduce)
            blockExp = blockExp.ReduceAndCheck();
        blockExp = blockExp.ReduceExtensions();

        var lambda = Expression.Lambda<Action<TSource, TTarget>>(blockExp, sourceInstance, targetInstance);

        return lambda.Compile();
    }

    private static IEnumerable<Expression> BuildPropertyGettersSetters(
        ParameterExpression sourceInstance,
        ParameterExpression targetInstance,
        IEnumerable<PropertyMap> properties) {

        var statements = new List<Expression>();

        foreach (var property in properties) {

            // value-getter
            var sourceGetterCall = Expression.Call(sourceInstance, property.SourceProperty.GetGetMethod());
            var sourcePropExp = Expression.TypeAs(sourceGetterCall, typeof(object));

            // value-setter
            var targetSetterCall =
                    Expression.Call(
                        targetInstance,
                        property.TargetProperty.GetSetMethod(),
                        Expression.Convert(sourceGetterCall, property.TargetProperty.PropertyType)
                        );
            var refNotNullExp = Expression.ReferenceNotEqual(sourceInstance, Expression.Constant(null));
            var propNotNullExp = Expression.ReferenceNotEqual(sourcePropExp, Expression.Constant(null));
            var notNullExp = Expression.And(refNotNullExp, propNotNullExp);
            var ifExp = Expression.IfThen(notNullExp, targetSetterCall);

            statements.Add(ifExp);
        }

        return statements;
    }

}

私にはすべて問題ないように思えますが、テストしようとすると、null 参照例外が発生します。テスト オブジェクトとメソッド:

public class UserEntity {

    public string Name { get; set; }
    public string Family { get; set; }
    public int Age { get; set; }
    public string Nickname { get; set; }

}

public class UserModel {

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public string Nickname { get; set; }

}

public static class CallTest {

    public static void Call() {
        var entity = new UserEntity {
            Name="Javad",
            Family="Amiry",
            Age = 25,
            Nickname = "my nickname is here",
        };
        var model = new UserModel();

        var map1 = new PropertyMap {
            SourceProperty = entity.GetType().GetProperty("Age"),
            TargetProperty = model.GetType().GetProperty("Age"),
        };
        var map2 = new PropertyMap {
            SourceProperty = entity.GetType().GetProperty("Nickname"),
            TargetProperty = model.GetType().GetProperty("Nickname"),
        };

        var action = MyUtility.BuildMapAction<UserEntity, UserModel>(new[] {map1, map2});
        action(entity, model); // here I get the error System.NullReferenceException: 'Object reference not set to an instance of an object.'
    }

}

そこで何が起こっているか分かりますか?私が逃したものは何ですか?


: サードパーティのマッパー (AutoMapper など) は使用できません

4

1 に答える 1