Automapper. Класс с коллекцией в коллекцию классов.
#39923360
Ссылка:
Ссылка на сообщение:
Ссылка с названием темы:
Ссылка на профиль пользователя:
|
Участник
Откуда: Минск
Сообщения: 1 886
|
|
Добрый день.
.Net Core 3.1 + AutoMapper 9.0.0
В первом спойлере настроил автомаппер - работает. Из минусов, придется для всех классов (примерно очень много штук прописывать ConvertUsing)
Во втором спойлере попытка этого избежать и он не работает. Собственно можно ли настроить так, чтобы упросить настройку.
Ессно полей в классах больше, чем в тестовом примере.
Рабочий способ:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119.
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp12
{
public interface ICommand
{
Int32 ID { get; set; }
}
public interface ICommand<T> : ICommand
{
IEnumerable<T> Items { get; set; }
}
public class Command : ICommand
{
public Int32 ID { get; set; }
}
public class Command<T> : Command, ICommand<T>
{
public IEnumerable<T> Items { get; set; }
}
public interface IItem { }
public class ItemA : IItem
{
public String Name { get; set; }
}
public class ItemB : IItem
{
public String Name { get; set; }
}
public class ItemC : IItem
{
public String Name { get; set; }
}
public class CommandA : Command<ItemA> { }
public class CommandB : Command<ItemB> { }
public class CommandC : Command<ItemC> { }
public class DTO
{
public Int32 IDID { get; set; }
public String Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
var sa = new CommandA { ID = 1, Items = new List<ItemA> { new ItemA { Name = "A" }, new ItemA { Name = "B" } } };
var sb = new CommandB { ID = 2, Items = new List<ItemB> { new ItemB { Name = "C" }, new ItemB { Name = "D" } } };
var sc = new CommandC { ID = 3, Items = new List<ItemC> { new ItemC { Name = "E" }, new ItemC { Name = "F" } } };
var config = new MapperConfiguration(x =>
{
x.CreateMap<ICommand, DTO>()
.ForMember(d => d.IDID, opt => opt.MapFrom(src => src.ID));
x.CreateMap<ItemA, DTO>();
x.CreateMap<ItemB, DTO>();
x.CreateMap<ItemC, DTO>();
x.CreateMap<CommandA, IEnumerable<DTO>>()
.ConvertUsing( (src, dst, ctx) =>
src.Items.Select(s =>
{
var x = ctx.Mapper.Map<DTO>(s);
return ctx.Mapper.Map(src, x);
})
);
x.CreateMap<CommandB, IEnumerable<DTO>>()
.ConvertUsing((src, dst, ctx) =>
src.Items.Select(s =>
{
var x = ctx.Mapper.Map<DTO>(s);
return ctx.Mapper.Map(src, x);
})
);
x.CreateMap<CommandC, IEnumerable<DTO>>()
.ConvertUsing((src, dst, ctx) =>
src.Items.Select(s =>
{
var x = ctx.Mapper.Map<DTO>(s);
return ctx.Mapper.Map(src, x);
})
);
}
);
var mapper = config.CreateMapper();
var a = mapper.Map<CommandA, IEnumerable<DTO>>(sa);
var b = mapper.Map<CommandB, IEnumerable<DTO>>(sb);
var c = mapper.Map<CommandC, IEnumerable<DTO>>(sc);
foreach (var x in a)
{
Console.WriteLine("{0}, {1}", x.IDID, x.Name);
}
foreach (var x in b)
{
Console.WriteLine("{0}, {1}", x.IDID, x.Name);
}
foreach (var x in c)
{
Console.WriteLine("{0}, {1}", x.IDID, x.Name);
}
Console.ReadKey();
}
}
}
Из минусов видно, что для каждой такой пары CommandA -> IEnumerable<DTO> надо писать ConvertUsing
Собственно хочется один раз его прописать для пары ICommand<IItem> -> IEnumerable<DTO> и дальше только просто указывать карту мапки для наследуемых типов.
Что-то вроде такого:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
var config = new MapperConfiguration(x =>
{
x.CreateMap<ICommand, DTO>()
.ForMember(d => d.IDID, opt => opt.MapFrom(src => src.ID));
x.CreateMap<ItemA, DTO>();
x.CreateMap<ItemB, DTO>();
x.CreateMap<ItemC, DTO>();
x.CreateMap<ICommand<IItem>, IEnumerable<DTO>>()
.ConvertUsing((src, dst, ctx) =>
src.Items.Select(s =>
{
var x = ctx.Mapper.Map<DTO>(s);
return ctx.Mapper.Map(src, x);
})
);
x.CreateMap<CommandA, IEnumerable<DTO>>();
x.CreateMap<CommandB, IEnumerable<DTO>>();
x.CreateMap<CommandC, IEnumerable<DTO>>();
}
);
Но это не работает и выдает ошибку Method 'GetEnumerator' in type ... does not have an implementation.'
|
|