AutoMapper - 在源端映射没有抽象类的派生类

时间:2010-12-16 10:39:39

标签: c# .net automapper

我正在尝试映射以下场景:

// SourceA + SourceB to not derive from a shared base class.
class SourceCollection
{
    IList<SourceA> ACollection;
    IList<SourceB> BCollection;

    // ... other properties ...
}

class DestCollection
{
    IList<DestBase> Collection;

    // ... other properties ...
}

abstract class DestBase { }

// In their destination form, DestA + DestB share DestBase as a base class.
class DestA : DestBase { }
class DestB : DestBase { }

当我映射SourceCollection&gt; DestCollection我希望将每个集合收集到一个集合中。理想情况下,我想在没有自定义解析器的情况下执行此操作,因为AutoMapper了解如何映射SourceA&gt; DestA和SourceB&gt; DestB罚款。我只是需要它来实现SourceA可以作为DestA映射到DestBase,因为DestA派生自DestBase。

由于没有SourceBase,我不能将其映射到DestBase并使用.Include。

我猜这可能需要一个自定义解析器,因为它是两个合并为一个的集合(我只希望结果是连接的),但如果它不需要它会很好。或者至少我可以编写一个通用的自定义解析器,如果SourceC + DestC出现,它就不需要更改。

更新

这是一个可以实现的ValueResolver,但是它确实需要考虑每种类型来手动解决:

public class BaseCollectionResolver : ValueResolver< SourceCollection, IList<DestBase> >
{
    protected override IList<DestBase> ResolveCore(SourceCollection source)
    {
        var items = new List<DestBase>();

        foreach (var sourceA in source.ACollection)
            items.Add( Mapper.Map<SourceA, DestA>(sourceA) );

        foreach (var sourceB in source.BCollection)
            items.Add( Mapper.Map<SourceB, DestB>(sourceB) );

        return items;
    }
}

然后相应地映射:

Mapper.CreateMap<SourceCollection, DestCollection>()
      .ForMember(dest => dest.Collection, m => m.ResolveUsing<BaseCollectionResolver>());

1 个答案:

答案 0 :(得分:1)

如果不使用ITypeConverter

,我无法想到一个很好的方法
public class SourceCollectionToDestCollection 
    : ITypeConverter<SourceCollection, DestCollection>
{
    public DestCollection Convert(ResolutionContext context)
    {
        SourceCollection source = context.SourceValue as SourceCollection;

        DestCollection destination = context.DestinationValue as DestCollection 
            ?? new DestCollection();

        foreach (var sourceA in source.ACollection)
        {
            DestA dest = Mapper.Map<SourceA, DestA>(sourceA);
            destination.Collection.Add(dest);
        }

        foreach (var sourceB in source.BCollection)
        {
            DestB dest = Mapper.Map<SourceB, DestB>(sourceB);
            destination.Collection.Add(dest);
        }

        return destination;
    }
}

并将其添加到映射器:

Mapper.CreateMap<SourceCollection, DestCollection>()
    .ConvertUsing<SourceCollectionToDestCollection>();