ฉันค่อนข้างใหม่ที่. NET และฉันตัดสินใจที่จะติดตั้ง. NET Core แทนที่จะเรียนรู้ "วิธีการแบบเก่า" ฉันพบบทความโดยละเอียดเกี่ยวกับการตั้งค่า AutoMapper สำหรับ. NET Core ที่นี่แต่มีคำแนะนำง่ายๆสำหรับมือใหม่หรือไม่?
ฉันค่อนข้างใหม่ที่. NET และฉันตัดสินใจที่จะติดตั้ง. NET Core แทนที่จะเรียนรู้ "วิธีการแบบเก่า" ฉันพบบทความโดยละเอียดเกี่ยวกับการตั้งค่า AutoMapper สำหรับ. NET Core ที่นี่แต่มีคำแนะนำง่ายๆสำหรับมือใหม่หรือไม่?
คำตอบ:
ฉันคิดออก! นี่คือรายละเอียด:
เพิ่ม AutoMapper พึ่งพาการฉีดแพคเกจเพื่อแก้ปัญหาของคุณผ่านทางNuGet
สร้างคลาสใหม่สำหรับโปรไฟล์การแมป (ฉันสร้างคลาสในไดเรกทอรีโซลูชันหลักชื่อMappingProfile.cs
และเพิ่มรหัสต่อไปนี้) ฉันจะใช้ a User
และUserDto
วัตถุเป็นตัวอย่าง
public class MappingProfile : Profile {
public MappingProfile() {
// Add as many of these lines as you need to map your objects
CreateMap<User, UserDto>();
CreateMap<UserDto, User>();
}
}
จากนั้นเพิ่ม AutoMapperConfiguration ในที่Startup.cs
แสดงด้านล่าง:
public void ConfigureServices(IServiceCollection services) {
// .... Ignore code before this
// Auto Mapper Configurations
var mappingConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new MappingProfile());
});
IMapper mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);
services.AddMvc();
}
ในการเรียกใช้วัตถุที่แมปในรหัสให้ทำสิ่งต่อไปนี้:
public class UserController : Controller {
// Create a field to store the mapper object
private readonly IMapper _mapper;
// Assign the object in the constructor for dependency injection
public UserController(IMapper mapper) {
_mapper = mapper;
}
public async Task<IActionResult> Edit(string id) {
// Instantiate source object
// (Get it from the database or whatever your code calls for)
var user = await _context.Users
.SingleOrDefaultAsync(u => u.Id == id);
// Instantiate the mapped data transfer object
// using the mapper you stored in the private field.
// The type of the source object is the first type argument
// and the type of the destination is the second.
// Pass the source object you just instantiated above
// as the argument to the _mapper.Map<>() method.
var model = _mapper.Map<UserDto>(user);
// .... Do whatever you want after that!
}
}
ฉันหวังว่านี่จะช่วยให้ใครบางคนเริ่มต้นใหม่ด้วย ASP.NET Core! ฉันยินดีรับข้อเสนอแนะหรือคำวิจารณ์ใด ๆ ในขณะที่ฉันยังใหม่กับโลก. NET!
Profile
ชั้นเรียนอยู่อย่างไร
ขั้นตอนในการใช้ AutoMapper กับ ASP.NET Core
ขั้นตอนที่ 1 การติดตั้ง AutoMapper ส่วนขยาย Microsoft.DependencyInject จาก NuGet Package
ขั้นตอนที่ 2 สร้างโฟลเดอร์ในโซลูชันเพื่อให้การแมปด้วยชื่อ "การแมป"
ขั้นตอนที่ 3 หลังจากเพิ่มโฟลเดอร์ Mapping เราได้เพิ่มคลาสที่มีชื่อ " MappingProfile " ชื่อนี้สามารถเป็นอะไรที่ไม่ซ้ำกันและดีที่จะเข้าใจ
ในคลาสนี้เราจะทำการแมปทั้งหมด
ขั้นตอน 4. เริ่มต้น Mapper ในการเริ่มต้น "ConfigureServices"
ในระดับเริ่มต้นเราจำเป็นต้องเริ่มต้นโปรไฟล์ที่เราได้สร้างและยังลงทะเบียนบริการ AutoMapper
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
ข้อมูลโค้ดเพื่อแสดงวิธีการ ConfigureServices ที่เราต้องเริ่มต้นและลงทะเบียน AutoMapper
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// Start Registering and Initializing AutoMapper
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
// End Registering and Initializing AutoMapper
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}}
ขั้นตอนที่ 5 รับเอาท์พุท
ในการรับผลลัพธ์ที่แมปเราจำเป็นต้องเรียก AutoMapper.Mapper.Map และส่งปลายทางและแหล่งที่มาที่เหมาะสม
AutoMapper.Mapper.Map<Destination>(source);
CodeSnippet
[HttpPost]
public void Post([FromBody] SchemeMasterViewModel schemeMaster)
{
if (ModelState.IsValid)
{
var mappedresult = AutoMapper.Mapper.Map<SchemeMaster>(schemeMaster);
}
}
'Mapper' does not contain a definition for 'initialize'
. ฉันใช้AutoMapper.Extensions.Microsoft.DependencyInjection
เวอร์ชั่น 7.0.0
ฉันต้องการขยายคำตอบของ @ theutz - คือบรรทัดนี้:
// services.AddAutoMapper(typeof(Startup)); // <-- newer automapper version uses this signature.
มีข้อผิดพลาด ( อาจเป็น ) ใน AutoMapper ส่วนขยาย Microsoft.DependencyInject รุ่น 3.2.0 (ฉันใช้. NET Core 2.0)
นี้เป็นความท้าทายในการนี้ปัญหา GitHub หากคลาสของคุณที่รับคลาสโปรไฟล์ของ AutoMapper มีอยู่ภายนอกแอสเซมบลีซึ่งเป็นคลาสเริ่มต้นคุณจะไม่ถูกลงทะเบียนหากการฉีด AutoMapper ของคุณมีลักษณะดังนี้:
services.AddAutoMapper();
เว้นแต่คุณจะระบุอย่างชัดเจนว่าแอสเซมบลีใดในการค้นหาโปรไฟล์ AutoMapper
มันสามารถทำได้เช่นนี้ในการเริ่มต้นของคุณกำหนดค่าบริการ:
services.AddAutoMapper(<assembies> or <type_in_assemblies>);
โดยที่"แอสเซมบลี"และ"type_in_assemblies"ชี้ไปที่แอสเซมบลีที่ระบุคลาสโปรไฟล์ในแอปพลิเคชันของคุณ เช่น:
services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));
ฉันคิดว่า (และฉันให้ความสำคัญกับคำนี้) เนื่องจากการใช้งานเกินพิกัดแบบไม่มีพารามิเตอร์ (ซอร์สโค้ดจากGitHub ):
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
}
เราพึ่งพา CLR ที่มีแอสเซมบลี JITed ที่มีโปรไฟล์ AutoMapper ซึ่งอาจเป็นหรืออาจไม่เป็นจริงเนื่องจากมีการ jitted เมื่อจำเป็นเท่านั้น (รายละเอียดเพิ่มเติมในคำถาม StackOverflow นี้ )
คำตอบ theutz 'ที่นี่ดีมากฉันแค่ต้องการเพิ่มนี้:
หากคุณปล่อยให้โปรไฟล์การจับคู่ของคุณสืบทอดมาMapperConfigurationExpression
แทนคุณProfile
สามารถเพิ่มการทดสอบเพื่อยืนยันการตั้งค่าการจับคู่ของคุณซึ่งมีประโยชน์เสมอ:
[Fact]
public void MappingProfile_VerifyMappings()
{
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(mappingProfile);
var mapper = new Mapper(config);
(mapper as IMapper).ConfigurationProvider.AssertConfigurationIsValid();
}
ฉันแก้ไขด้วยวิธีนี้ (คล้ายกับด้านบน แต่ฉันรู้สึกว่ามันเป็นโซลูชันที่สะอาดกว่า) สำหรับ. NET Core 2.2 / Automapper 8.1.1 w / Extensions.DI 6.1.1
สร้างคลาส MappingProfile.cs และสร้างตัวสร้างด้วย Maps (ฉันวางแผนที่จะใช้คลาสเดียวเพื่อเก็บการแมปทั้งหมดของฉัน)
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Source, Dest>().ReverseMap();
}
}
ใน Startup.cs ให้เพิ่มด้านล่างเพื่อเพิ่มลงใน DI (แอสเซมบลี arg สำหรับคลาสที่เก็บการกำหนดค่าการแมปของคุณในกรณีของฉันคือคลาส MappingProfile)
//add automapper DI
services.AddAutoMapper(typeof(MappingProfile));
ในตัวควบคุมให้ใช้เหมือนกับที่คุณต้องการวัตถุ DI อื่น ๆ
[Route("api/[controller]")]
[ApiController]
public class AnyController : ControllerBase
{
private readonly IMapper _mapper;
public AnyController(IMapper mapper)
{
_mapper = mapper;
}
public IActionResult Get(int id)
{
var entity = repository.Get(id);
var dto = _mapper.Map<Dest>(entity);
return Ok(dto);
}
}
ใน Startup.cs ของฉัน (Core 2.2, Automapper 8.1.1)
services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
ในโครงการเข้าถึงข้อมูลของฉัน
namespace DAL
{
public class MapperProfile : Profile
{
// place holder for AddAutoMapper (to bring in the DAL assembly)
}
}
ในนิยามรุ่นของฉัน
namespace DAL.Models
{
public class PositionProfile : Profile
{
public PositionProfile()
{
CreateMap<Position, PositionDto_v1>();
}
}
public class Position
{
...
}
services.AddAutoMapper( typeof(DAL.MapperProfile) );
แทน services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
?
ฉันชอบคำตอบมากมายโดยเฉพาะ @saineshwar ฉันกำลังใช้. net Core 3.0 กับ AutoMapper 9.0 ดังนั้นฉันรู้สึกว่าถึงเวลาที่ต้องตอบคำถาม
สิ่งที่ใช้ได้ผลสำหรับฉันคือ Startup.ConfigureServices (... ) ลงทะเบียนบริการด้วยวิธีนี้:
services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>(),
AppDomain.CurrentDomain.GetAssemblies());
ฉันคิดว่าคำตอบที่เหลือของ @saineshwar จะสมบูรณ์แบบ แต่ถ้าใครสนใจรหัสคอนโทรลเลอร์ของฉันคือ:
[HttpGet("{id}")]
public async Task<ActionResult> GetIic(int id)
{
// _context is a DB provider
var Iic = await _context.Find(id).ConfigureAwait(false);
if (Iic == null)
{
return NotFound();
}
var map = _mapper.Map<IicVM>(Iic);
return Ok(map);
}
และชั้นเรียนทำแผนที่ของฉัน:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Iic, IicVM>()
.ForMember(dest => dest.DepartmentName, o => o.MapFrom(src => src.Department.Name))
.ForMember(dest => dest.PortfolioTypeName, o => o.MapFrom(src => src.PortfolioType.Name));
//.ReverseMap();
}
}
----- แก้ไข -----
หลังจากอ่านเอกสารที่ลิงก์ในความคิดเห็นโดย Lucian Bargaoanu ฉันคิดว่าการเปลี่ยนคำตอบนี้จะดีกว่า
พารามิเตอร์ services.AddAutoMapper()
(ที่มี @saineshwar คำตอบ) ไม่ทำงานอีกต่อไป (อย่างน้อยสำหรับฉัน) แต่ถ้าคุณใช้แอสเซมบลี AutoMapper ของ NuGet ส่วนขยาย MicrosoftDependencyInject เฟรมเวิร์กสามารถตรวจสอบคลาสทั้งหมดที่ขยาย AutoMapper.Profile (เช่นเดียวกับ MappingProfile)
ดังนั้นในกรณีของฉันที่คลาสเป็นของแอสเซมบลีที่ดำเนินการเดียวกันการลงทะเบียนบริการสามารถย่อให้สั้นลงservices.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(วิธีที่สวยงามกว่านั้นอาจเป็นส่วนขยายแบบไม่มีพารามิเตอร์ด้วยการเข้ารหัสนี้)
ขอบคุณลูเชีย!
ฉันใช้ AutoMapper 6.1.1 และ asp.net Core 1.1.2
ก่อนอื่นกำหนดคลาสโปรไฟล์ที่สืบทอดโดย Profile Class ของ Automapper ฉันสร้างอินเทอร์เฟซ IProfile ซึ่งว่างเปล่ามีวัตถุประสงค์เพื่อค้นหาคลาสของประเภทนี้เท่านั้น
public class UserProfile : Profile, IProfile
{
public UserProfile()
{
CreateMap<User, UserModel>();
CreateMap<UserModel, User>();
}
}
ตอนนี้สร้างคลาสที่แยกต่างหากเช่นการแมป
public class Mappings
{
public static void RegisterMappings()
{
var all =
Assembly
.GetEntryAssembly()
.GetReferencedAssemblies()
.Select(Assembly.Load)
.SelectMany(x => x.DefinedTypes)
.Where(type => typeof(IProfile).GetTypeInfo().IsAssignableFrom(type.AsType()));
foreach (var ti in all)
{
var t = ti.AsType();
if (t.Equals(typeof(IProfile)))
{
Mapper.Initialize(cfg =>
{
cfg.AddProfiles(t); // Initialise each Profile classe
});
}
}
}
}
ขณะนี้อยู่ใน MVC Core web Project ในไฟล์ Startup.cs ใน Constructor ให้เรียกคลาส Mapping ซึ่งจะเริ่มต้นการแม็พทั้งหมดในเวลาที่ทำการโหลดแอปพลิเคชัน
Mappings.RegisterMappings();
สำหรับ ASP.NET Core (ทดสอบโดยใช้ 2.0+ และ 3.0) หากคุณต้องการอ่านเอกสารประกอบแหล่งที่มา: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInject/blob/master/README.md
มิฉะนั้นการทำตาม 4 ขั้นตอนเหล่านี้ใช้งานได้:
ติดตั้ง AutoMapper ส่วนขยาย Microsoft.DependancyInject จาก nuget
เพียงเพิ่มบางคลาสโปรไฟล์
จากนั้นเพิ่มด้านล่างลงในคลาส startup.cs ของคุณ
services.AddAutoMapper(OneOfYourProfileClassNamesHere)
จากนั้นเพียงฉีด IMapper ในอุปกรณ์ควบคุมหรือที่ใดก็ตามที่คุณต้องการ:
public class EmployeesController {
private readonly IMapper _mapper;
public EmployeesController(IMapper mapper){
_mapper = mapper;
}
และถ้าคุณต้องการใช้ ProjectTo เพียงแค่นี้:
var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync()
สำหรับ AutoMapper 9.0.0:
public static IEnumerable<Type> GetAutoMapperProfilesFromAllAssemblies()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var aType in assembly.GetTypes())
{
if (aType.IsClass && !aType.IsAbstract && aType.IsSubclassOf(typeof(Profile)))
yield return aType;
}
}
}
MapperProfile:
public class OrganizationProfile : Profile
{
public OrganizationProfile()
{
CreateMap<Foo, FooDto>();
// Use CreateMap... Etc.. here (Profile methods are the same as configuration methods)
}
}
ในการเริ่มต้นของคุณ:
services.AddAutoMapper(GetAutoMapperProfilesFromAllAssemblies()
.ToArray());
ในตัวควบคุมหรือบริการ: Inject mapper:
private readonly IMapper _mapper;
การใช้งาน:
var obj = _mapper.Map<TDest>(sourceObject);
ใน asp.net รุ่นล่าสุดคุณควรใช้การเริ่มต้นต่อไปนี้:
services.AddAutoMapper(typeof(YourMappingProfileClass));
Asp.Net Core 2.2 พร้อม AutoMapper ส่วนขยาย Microsoft.DependencyInject
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Domain, DomainDto>();
}
}
ใน Startup.cs
services.AddAutoMapper(typeof(List.Handler));
เพื่อเพิ่มสิ่งที่ Arve Systad กล่าวถึงสำหรับการทดสอบ ถ้าด้วยเหตุผลใดก็ตามที่คุณชอบฉันและต้องการรักษาโครงสร้างการสืบทอดที่ให้ไว้ในโซลูชัน theutz คุณสามารถตั้งค่า MapperConfiguration ดังนี้:
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(mappingProfile);
});
var mapper = new Mapper(config);
ฉันทำสิ่งนี้ใน NUnit
services.AddAutoMapper (); ไม่ได้ผลสำหรับฉัน (ฉันใช้ Asp.Net Core 2.0)
หลังจากกำหนดค่าดังต่อไปนี้
var config = new AutoMapper.MapperConfiguration(cfg =>
{
cfg.CreateMap<ClientCustomer, Models.Customer>();
});
เริ่มต้น mapper IMapper mapper = config.CreateMapper ();
และเพิ่มออบเจกต์ mapper ไปยังบริการเป็น singleton servicesAddSingleton (mapper);
วิธีนี้ฉันสามารถเพิ่ม DI ลงในคอนโทรลเลอร์ได้
private IMapper autoMapper = null;
public VerifyController(IMapper mapper)
{
autoMapper = mapper;
}
และฉันใช้ตามด้านล่างในวิธีการกระทำของฉัน
ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
เกี่ยวกับคำตอบของ theutz คุณไม่จำเป็นต้องระบุพารามิเตอร์ papper ของ mapper IMapper ที่ constructor ตัวควบคุม
คุณสามารถใช้ Mapper เพราะมันเป็นสมาชิกแบบคงที่ในสถานที่ใด ๆ ของรหัส
public class UserController : Controller {
public someMethod()
{
Mapper.Map<User, UserDto>(user);
}
}
IMapper
คุณสามารถเยาะเย้ยและตัวอย่างเช่นเพียงทำให้มันกลับเป็นโมฆะถ้ามันไม่เกี่ยวข้องกับการทดสอบที่กำหนด