如何使用Automapper将对象映射到不同级别的接口?

时间:2014-12-12 21:51:00

标签: c# automapper

我是Automapper的新手,我正在尝试将数据从列表中的对象映射到列表中的接口。除此之外,列表位于包含对象的不同级别:

// class definitions
public class MyViewModel
{
    public int ViewModelId { get; set; }
    public IList<ViewItem> Page1Selections { get; set; }
    public IList<ViewItem> Page2Selections { get; set; }
}

public class ViewItem
{
    public int ItemId { get; set; }
    public bool IsSelected { get; set; }
}

public class MyDbModel
{
    public int DbModelId { get; set; }
    public IPageSelection Page1Selections { get; set; }
    public IPageSelection Page2Selections { get; set; }
}

public interface IPageSelection
{
    int PageNumber { get; set; }
    IList<IMyDbItem> PageSelections { get; set; }
}

public class PageSelection : IPageSelection
{
    public int PageNumber { get; set; }
    public IList<IMyDbItem> PageSelections { get; set; }
}

public interface IMyDbItem
{
    int ItemId { get; set; }
    bool IsSelected { get; set; }
}

public class MyDbItem : IMyDbItem
{
    public int ItemId { get; set; }
    public bool IsSelected { get; set; }
}


    // mapping code
    MyViewModel myVm = new MyViewModel();
    myVm.ViewModelId = 123;
    myVm.Page1Selections = new List<ViewItem>();
    myVm.Page1Selections.Add(new ViewItem() { ItemId = 1, IsSelected = true });
    myVm.Page2Selections = new List<ViewItem>();
    myVm.Page2Selections.Add(new ViewItem() { ItemId = 2, IsSelected = true });

    Mapper.Initialize(cfg =>
    {
        cfg.BindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
        cfg.CreateMap<MyViewModel, MyDbModel>();
        cfg.CreateMap<ViewItem, IMyDbItem>();
    });

    MyDbModel myDb = new MyDbModel();
    myDb = Mapper.Map<MyDbModel>(myVm); //<== exception here

很抱歉长篇大论。但我正在与对象接口和层次不匹配映射问题进行斗争。

1 个答案:

答案 0 :(得分:1)

这是你可以实现这一目标的一种方式:

cfg.CreateMap<MyViewModel, MyDbModel>()
    .ForMember(dest => dest.DbModelId, opt => opt.MapFrom(src => src.ViewModelId));

cfg.CreateMap<ViewItem, IMyDbItem>()
    .ConstructUsing((ViewItem src) => new MyDbItem());

cfg.CreateMap<IList<ViewItem>, IPageSelection>()
    .ConstructUsing((IList<ViewItem> src) => new PageSelection())
    .ForMember(dest => dest.PageSelections, opt => opt.MapFrom(src => src))
    .ForMember(dest => dest.PageNumber, opt => opt.Ignore());

您收到的错误是因为IList<ViewItem>IPageSelection之间没有映射。我在上面创建了这个映射。

重要的一点是ConstructUsing电话。我在这里添加了这些,因为我假设你想使用实现你所映射的接口的具体类型。否则,AutoMapper将创建一个实现目标接口的代理类。

允许从IPageSelection.PageSelections映射到IList<ViewItem>的部分是opt.MapFrom(src => src)部分。这实际上告诉AutoMapper从列表映射到内部PageSelections属性,最终使用从ViewItemIMyDbItem的映射。

示例: https://dotnetfiddle.net/DW9dfO