AutoMapper Map and Flatten Entity with List
I have the following data model
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; }
}
And I want to map it to the following Dto
public class ProductDto
{
public name Name{ get; set; }
public double UnitSize { get; set; }
public int ItemsPerPack { get; set; }
public double Price{ get; set; }
}
I have read into using AutoMapper for this, but am unsure how to setup the configuration because there would be 4 sources mapping to one destination, all from lists. I would expect to there to be multiple items with the same property values and that is desired. Do I have to ForMember<> map for each item?
您可以在自定义类型转换器中执行此操作:
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);
Stuartd's answer is great. But now I am thinking why even rely on AutoMapper at this point. We can just do this:
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();
}
}
I ran this as a test and without AutoMapper it takes .0000768 and with AutoMapper it takes .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();
}
The only downside I see is the coupling of Products to ProductDto. I am not sure if this should be a comment. I guess it is another approach.
链接地址: http://www.djcxy.com/p/37378.html上一篇: 自动映射器,映射到一个复杂的对象