AutoMapper 2.2.1 DynamicMap不映射底层类型属性(2.2.0可以)

本文关键字:属性 可以 类型 DynamicMap 映射 AutoMapper | 更新日期: 2023-09-27 18:05:24

我最近从AutoMapper 2.2.0升级到2.2.1和一个泛型方法我已经停止正确映射。下面是该方法的伪版本:

public void LoadModel<TModel>(int id, TModel model) where TModel : ModelBase
{
    var entity = _repo.LoadById(id);
    _mapper.DynamicMap(entity, model);
    model.AfterMap(); // AfterMap is a virtual method in ModelBase
}

ModelBase是一个抽象类,由传递给该方法的父类的实例继承。在2.2.0版本中,entity实例对应的属性被正确映射到model实例的ModelBase属性;升级到2.2.1版本后,ModelBase上的属性不再映射——没有抛出异常,只是属性没有被设置。

更新:下面是一个演示2.2.0和2.2.1之间区别的具体示例。在2.2.0版本中,输出将是:

Male
True

在2.2.1版本中,输出将是:

Male
False

Human中的IsEmployed属性在2.2.1版本中没有被映射,但在2.2.0版本中被映射。下面是示例代码:

namespace TestAutomapper
{
    using System;
    class Program
    {
        static void Main(string[] args)
        {
            Tester tester = new Tester();
            tester.Test();
        }
    }
    public class Tester
    {
        public void Test()
        {
            var animal = (Animal)new Human();
            LoadModel(animal);
            var human = (Human)animal;
            Console.WriteLine(human.Gender);
            Console.WriteLine(human.IsEmployed.ToString());
            Console.ReadLine();
        }
        private void LoadModel<TModel>(TModel model) where TModel : Animal
        {
            var tim = new Developer { Gender = "Male", IsEmployed = true, KnownLanguages = 42 };
            AutoMapper.Mapper.DynamicMap(tim, model);
        }
    }
    public abstract class Animal
    {
        public string Gender { get; set; }
    }
    public class Human : Animal
    {
        public bool IsEmployed { get; set; }
    }
    public class Developer
    {
        public string Gender { get; set; }
        public bool IsEmployed { get; set; }
        public int KnownLanguages { get; set; }
    }
}

这个问题似乎与Human在被映射之前被装箱为Animal有关。我并不是说这是一个bug,但它在不同版本之间的表现肯定是不同的。

更新2:我的例子中的抽象类是一个转移注意力的东西;如果我使用一个叫做IAnimal的接口而不是一个叫做Animal的抽象类,这个例子就成立。这个问题似乎清楚地表明,版本2.2.0在动态映射时考虑了底层类型,而版本2.2.1没有。

AutoMapper 2.2.1 DynamicMap不映射底层类型属性(2.2.0可以)

2.2.0和2.2.1之间的动态映射有变化

在2.2.0中,代码是这样的:
public void DynamicMap<TSource, TDestination>(TSource source, TDestination destination)
{
    Type modelType = typeof(TSource);
    Type destinationType = (Equals(destination, default(TDestination)) ? typeof(TDestination) : destination.GetType());
    DynamicMap(source, destination, modelType, destinationType);
}

和2.2.1中的

public void DynamicMap<TSource, TDestination>(TSource source, TDestination destination)
{
    Type modelType = typeof(TSource);
    Type destinationType = typeof(TDestination);
    DynamicMap(source, destination, modelType, destinationType);
}

这实际上意味着在2.2.0中动态映射的目标类型是由目标值决定的。如果它为空(对于引用类型),则从TDestination获取目标;否则由目标对象实例的类型决定。

在AutoMapper 2.2.1中,TDestination类型总是优先的,在你的例子中是Animal。