【问题标题】:AutoMapper - Mapping derived classes without abstract class on source sideAutoMapper - 在源端映射没有抽象类的派生类
【发布时间】:2010-12-16 19:17:43
【问题描述】:

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

// 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 > DestCollection 时,我希望将每个集合收集到一个集合中。理想情况下,我想在没有自定义解析器的情况下执行此操作,因为 AutoMapper 了解如何很好地映射 SourceA > DestA 和 SourceB > 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>());

【问题讨论】:

    标签: c# .net automapper


    【解决方案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>();
    

    【讨论】:

    • 谢谢,因为 SourceCollection 将包含当前映射到 DestCollection 的其他属性(我在示例中省略了它们),ConvertUsing 会阻止它们被映射吗?
    • @PirateKitten - 老实说我不知道​​。我从来没有尝试过,因为我现在总是在 ITypeConverters 中进行所有映射。试一试,让我知道会发生什么:)。
    • 我认为它需要一个仅针对该字段的值解析器,而不是整个集合。我已经修改了您的代码并更新了我的问题。这个解决方案有效,但我希望 AutoMapper 的一部分我丢失了可能已经处理了这种情况:)
    猜你喜欢
    • 2021-08-04
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多