c# - 复杂对象/嵌套映射中的自动映射器和映射列表

标签 c# automapper-3

我正忙着从旧的 map 标准转换为自动映射器。

这是我的类(class)

// Models
public class BaseModel
{
    public Int64 Id { get; set; }
    public Guid UniqueId { get; set; }
    public DateTime? CreateDate { get; set; }
    public DateTime? LastUpdate { get; set; }
} 

public class LibraryItemModel : BaseModel
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string URL { get; set; }
    public bool IsActive { get; set; }
    public List<LibraryCategoryModel> Categories { get; set; }
}   

public class LibraryCategoryModel : BaseModel
{
    public string Description { get; set; }
}


// Entity Classes

public partial class LibraryItem
{
    public LibraryItem()
    {
        this.LibraryItemCategories = new HashSet<LibraryItemCategory>();
    }

    public long Id { get; set; }
    public System.Guid UniqueId { get; set; }
    public string Description { get; set; }
    public string URL { get; set; }
    public System.DateTime CreateDate { get; set; }
    public System.DateTime LastUpdate { get; set; }
    public bool IsActive { get; set; }
    public string Name { get; set; }

    public virtual ICollection<LibraryItemCategory> LibraryItemCategories { get; set; }
}
// comes from a ternary table in DB... many to many
public partial class LibraryItemCategory
{
    public long LibraryItemId { get; set; }
    public long LibraryCategoryId { get; set; }
    public System.DateTime CreateDate { get; set; }
    public System.DateTime LastUpdate { get; set; }

    public virtual LibraryCategory LibraryCategory { get; set; }
    public virtual LibraryItem LibraryItem { get; set; }
}

public partial class LibraryCategory
{
    public LibraryCategory()
    {
        this.LibraryCategoryRoles = new HashSet<LibraryCategoryRole>();
        this.LibraryItemCategories = new HashSet<LibraryItemCategory>();
    }

    public long id { get; set; }
    public System.Guid UniqueId { get; set; }
    public string Description { get; set; }
    public System.DateTime CreateDate { get; set; }
    public System.DateTime LastUpdate { get; set; }

    public virtual ICollection<LibraryCategoryRole> LibraryCategoryRoles { get; set; }
    public virtual ICollection<LibraryItemCategory> LibraryItemCategories { get; set; }
}


    // Old Conversion code doing it the long way

    private LibraryItemModel Convert(Entities.LibraryItem libraryItem)
    {

        var newLibraryItem = new LibraryItemModel
        {
            UniqueId = libraryItem.UniqueId,
            Name = libraryItem.Name,
            Description = libraryItem.Description,
            URL = libraryItem.URL,
            CreateDate = libraryItem.CreateDate,
            LastUpdate = libraryItem.LastUpdate,
            IsActive = libraryItem.IsActive,
            Categories = new List<LibraryCategoryModel>()
        };

        foreach (var lc in libraryItem.LibraryItemCategories)
        {
            var newCategory = new LibraryCategoryModel
            {
                UniqueId = lc.LibraryCategory.UniqueId,
                Description = lc.LibraryCategory.Description,
                CreateDate = lc.LibraryCategory.CreateDate,
                LastUpdate = lc.LibraryCategory.LastUpdate
            };

            newLibraryItem.Categories.Add(newCategory);
        }

        return newLibraryItem;
    }


    // My attempt at automapper to go between the models and entities
    Mapper.CreateMap<EF.Entities.LibraryItem, LibraryItemModel>();
    Mapper.CreateMap<LibraryItemModel, EF.Entities.LibraryItem>();
          .ForMember(lim => lim.LibraryItemCategories, o => o.Ignore()
    Mapper.CreateMap<EF.Entities.LibraryCategory, LibraryCategoryModel>();
    Mapper.CreateMap<LibraryCategoryModel, EF.Entities.LibraryCategory>()
          .ForMember(lcm => lcm.LibraryCategoryRoles, o => o.Ignore())
          .ForMember(lcm => lcm.LibraryItemCategories, o => o.Ignore());

无论我如何配置忽略或自定义映射,它似乎都不喜欢这种嵌套。那里的任何 Automapper 专家都可以告诉我如何使用像这样的复杂对象进行映射。实体类是通过 EF6 edmx 文件生成的。

最佳答案

所以基本上这里的问题是你想从每个 LibraryItemCategory 映射属于 LibraryItemLibraryCategoryModel其中包括每个 LibraryItemCatalog 的属性的 LibraryCatalog属性(property)。

首先,您要正确地将集合相互映射:

Mapper.CreateMap<LibraryItem, LibraryItemModel>()
    .ForMember(
        dest => dest.Categories, 
        opt => opt.MapFrom(src => src.LibraryItemCategories));

接下来你需要担心映射每个 LibraryItemCategory LibraryItem.LibraryItemCategories 内部到 LibraryCatalogModel .如问题所述,您需要访问每个 LibraryItemCategoryLibraryCatalog属性并实际从中映射。这看起来是这样的:

Mapper.CreateMap<LibraryItemCategory, LibraryCategoryModel>()
    .ConstructUsing(ct => Mapper.Map<LibraryCategoryModel>(ct.LibraryCategory))
    .ForAllMembers(opt => opt.Ignore());

在这里,我们告诉 AutoMapper 从 LibraryItemCategory 映射到 LibraryCategoryModel , 我们需要构造 LibraryCategoryModel正在使用另一个调用Mapper.Map在内LibraryCategory属性(property)。

接下来,剩下要做的就是定义从LibraryCategory 的映射。至 LibraryCategoryModel :

Mapper.CreateMap<LibraryCategory, LibraryCategoryModel>();

现在调用Mapper.MapLibraryItem 上应该为您打理一切。


或者,您可以从 LibraryItemCategory 中删除 map 至 LibraryCategoryModel并使用 LINQ 创建 LibraryCategory 的集合您实际上想从 LibraryItem 的映射定义中进行映射至 LibraryItemModel :

Mapper.CreateMap<LibraryItem, LibraryItemModel>()
    .ForMember(
        dest => dest.Categories, 
        opt => opt.MapFrom(
            src => src.LibraryItemCategories.Select(lb => lb.LibraryCategory)));

您显然仍然需要来自 LibraryCategory 的映射至 LibraryCategoryViewModel ,但您可能更喜欢这个,因为它涉及的映射更少。

关于c# - 复杂对象/嵌套映射中的自动映射器和映射列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24809956/

相关文章:

c# - 如何在不更改属性值的情况下运行属性集?

c# - 如何获取int的位大小

c# - 使用自动映射器将复杂的 DTO 映射到实体

Automapper 3.0 - 此平台不支持此类型 IMapperRegistry

c# - 在 ASP.NET 中异步填充数据集或数据表的最佳做法是什么?

c# - 访问 DotLiquid 中自己标签中的当前范围

c# - 我如何判断我的泛型类型是否支持某个接口(interface)并为函数来回转换到该接口(interface)?

automapper-3 - 使用自动映射器映射 COM 对象

c# - 如何使用 AutoMapper 从可枚举(或数组)列表属性映射到列表?

c# - AutoMapper 3 中的映射行为不一致