自动映射器解析使用泛型会导致"Value supplied is of type X but expected Y"错误



我有一个场景,我必须使用AutoMapper将DTO映射到域对象。这个映射需要一些复杂的管理,所以我创建了一个自定义值解析器。我想从FooDTO得到Foo。这两个对象之间的唯一区别是Foo有一个ICollection<Child>, FooDTO有一个TrackedData<ChildDTO>,其中TrackeData<T>是一个具有3个ICollection<T>的对象。这是我的简化场景:

public class TrackedData<T>
{
    public ICollection<T> Updated { get; set; }
    public ICollection<T> Created { get; set; }
    public ICollection<T> Deleted { get; set; }
    public TrackedData()
    {
        Updated = new List<T>();
        Created = new List<T>();
        Deleted = new List<T>();
    }
}
public class Foo
{
    private List<Child> _childs;
    public string Name { get; set; }
    public ICollection<Child> Childs
    {
        get
        {
            if (_childs == null)
                _childs = new List<Child>();
            return _childs;
        }
        set
        {
            _childs = (List<Child>)value;
        }
    }
}
public class Child
{
    public string Description { get; set; }
}
public class FooDTO
{
    public string Name { get; set; }
    public TrackedData<ChildDTO> Childs { get; set; }
}
public class ChildDTO
{
    public string Description { get; set; }
}
public class Program
{
    public static void Main(string[] args)
    {
        Mapper.CreateMap(typeof(TrackedData<>), typeof(TrackedData<>));
        Mapper.CreateMap<ChildDTO, Child>();
        Mapper.CreateMap<FooDTO, Foo>()
            .ForMember(d => d.Childs, opt => opt.ResolveUsing<TrackedDataResolver<ChildDTO, Child>>());
        FooDTO fooDTO = CreateFakeFooDTO();
        Foo foo = Mapper.Map<FooDTO, Foo>(fooDTO);
    }
    private static FooDTO CreateFakeFooDTO() { /* omitted for simplicity */ }
    private static TrackedData<ChildDTO> CreateFakeTrackedDataChildDTO() { /* omitted for simplicity */ }
    private static ICollection<ChildDTO> CreateFakeListChildDTO() { /* omitted for simplicity */ }
    private static ChildDTO CrateFakeChildDTO(){ /* omitted for simplicity */ }
}
public class TrackedDataResolver<TSource, TDestination> : ValueResolver<TrackedData<TSource>, ICollection<TDestination>>
{
    protected override ICollection<TDestination> ResolveCore(TrackedData<TSource> source)
    {
        TrackedData<TDestination> trackedDestination = new TrackedData<TDestination>();
        ICollection<TDestination> destination = new List<TDestination>();
        trackedDestination = Mapper.Map<TrackedData<TSource>, TrackedData<TDestination>>(source);
        foreach (var o in trackedDestination.Created)
        {
            // Do stuff...
            destination.Add(o);
        }
        foreach (var o in trackedDestination.Updated)
        {
            // Do stuff...
            destination.Add(o);
        }
        foreach (var o in trackedDestination.Deleted)
        {
            // Do stuff...
            destination.Add(o);
        }
        return destination;
    }
}

当执行这一行时

Foo foo = Mapper.Map<FooDTO, Foo>(fooDTO);

我得到这个错误:

{"提供的值类型为AutoMapperDemo。但期望AutoMapperDemo.TrackedData'1[automapperdemo . childto]。更改值解析器源类型,或使用FromMember重定向提供给值解析器的源值。rnValue的类型为AutoMapperDemo。但期望AutoMapperDemo.TrackedData'1[automapperdemo . childto]。更改值解析器源类型,或使用FromMember重定向提供给值解析器的源值。"}

源代码可在Github: https://github.com/josmonver/AutoMapperValueResolverIssue.git知道为什么会出现这个错误吗?

你可以在你的TrackedData<T>类中实现UnionAll方法(更新+创建+删除)并映射它,而不是把沉重的逻辑带入你的映射器:

    Mapper.CreateMap<FooDTO, Foo>()
        .ForMember(d => d.Childs, opt => opt.MapFrom(src => src.UnionAll()));

相关内容

最新更新