2016-11-28 38 views
1

,我有以下數據模型AutoMapper地圖和展平實體名單

public class Products 
{ 
    public string Name { get; set; } 
    public ICollection<ProductSize> ProductSizes { get; set; } 
} 

public class ProductSize 
{ 
    public double UnitSize { get; set; } 
    public ICollection<ProductPackage> ProductPackages { get; set; } 
} 

public class ProductPackage 
{ 
    public int ItemsPerPack { get; set; } 
    public ICollection<ProductPrice> ProductPrices { get; set; } 
} 

public class ProductPrice 
{ 
    public double Price{ get; set; } 
} 

而且我想它映射到下面的DTO

public class ProductDto 
{ 
    public name Name{ get; set; } 
    public double UnitSize { get; set; } 
    public int ItemsPerPack { get; set; } 
    public double Price{ get; set; } 
} 

我已經讀入使用AutoMapper這一點,但我不確定如何設置配置,因爲將有4個源映射到一個目標,全部來自列表。我期望在那裏有多個項目具有相同的屬性值,這是所需的。我必須爲每個項目的會員<>地圖嗎?

回答

1

你可以做一個Custom Type Converter

Func<Products, IEnumerable<ProductDto>> conversion = product => 
    from size in product.ProductSizes 
    from package in size.ProductPackages 
    from price in package.ProductPrices 
    select new ProductDto { 
     Name = product.Name, 
     UnitSize = size.UnitSize, 
     ItemsPerPack = package.ItemsPerPack, 
     Price = price.Price 
    }; 

Mapper.Initialize(c => c.CreateMap<Products, IEnumerable<ProductDto>>() 
         .ConvertUsing(conversion)); 


var product = GetProduct(…); 
var dtos = Mapper.Map<Products, IEnumerable<ProductDto>>(product); 
+0

完美,那就是訣竅 –

0

斯圖亞特的答案很好。但是現在我在思考爲什麼即使依賴AutoMapper。我們可以做這樣的:

public class Products { 
    public string Name { get; set; } 
    public ICollection<ProductSize> ProductSizes { get; set; } 

    public IList<ProductDto> ConvertTo() { 
     var q = from size in ProductSizes 
     from package in size.ProductPackages 
     from price in package.ProductPrices 
     select new ProductDto 
     { 
     Name = this.Name, 
     UnitSize = size.UnitSize, 
     ItemsPerPack = package.ItemsPerPack, 
     Price = price.Price 
     }; 

     return q.ToList(); 
    } 
} 

我跑這是一個試驗,沒有AutoMapper需要0.0000768與AutoMapper需要0.0836274:

class Program { 
static void Main(string[] args) { 
    var c = new ProductPackage 
    { 
     ProductPrices = new List<ProductPrice> { new ProductPrice() } 
    }; 
    var p = Enumerable.Range(1, 100000).Select(x => 
    new Products 
    { 
     Name = "Good Product", 
     ProductSizes = new List<ProductSize> { 
     new ProductSize { Name = "Small", UnitSize = 10, ProductPackages = new List<ProductPackage> { c } } } 
    }).ToList(); 

    Stopwatch w = new Stopwatch(); 
    w.Start(); 
    var dto = p.Select(x => x.ConvertTo()); 
    Console.WriteLine("Without AutoMapper it took: {0}", w.Elapsed); 
    w.Stop(); 

    DoWithAutoMapper(p); 

    Console.Read(); 
} 

private static void DoWithAutoMapper(List<Products> p) { 

    Func<Products, IEnumerable<ProductDto>> conversion = product => 
     from size in product.ProductSizes 
     from package in size.ProductPackages 
     from price in package.ProductPrices 
     select new ProductDto 
     { 
      Name = product.Name, 
      UnitSize = size.UnitSize, 
      ItemsPerPack = package.ItemsPerPack, 
      Price = price.Price 
     }; 

    Mapper.Initialize(c => c.CreateMap<Products, IEnumerable<ProductDto>>() 
           .ConvertUsing(conversion)); 

    Stopwatch w = new Stopwatch(); 
    w.Start(); 
    var products = p; 
    foreach(var item in p) { 

     var dtos = Mapper.Map<Products, IEnumerable<ProductDto>>(item); 
    } 
    Console.WriteLine("Using AutoMapper it took: {0}", w.Elapsed); 
    w.Stop(); 
} 

我看到的唯一的缺點是耦合產品到ProductDto。我不確定這是否應該是一個評論。我想這是另一種方法。

+0

我不認爲這是答案:如果我理解正確的問題OP希望Products'的'一個實例映射到ProductDto的'名單對象。此外,當源和目標名稱相同時,您不需要添加「ForMember」調用,這就是爲什麼它是** Auto **映射器。 – stuartd

+0

@stuartd你是對的,我想要一個產品的ProductDto列表(因爲有很多尺寸,包裝和價格) –

+0

@stuartd你能看到編輯,因爲你的答案啓發了這一點。其實大部分是你的答案。 – CodingYoshi