Tôi còn khá mới ở .NET và tôi quyết định giải quyết .NET Core thay vì học "những cách cũ". Tôi đã tìm thấy một bài viết chi tiết về việc thiết lập AutoMapper cho .NET Core ở đây , nhưng có một hướng dẫn đơn giản hơn cho người mới không?
Tôi còn khá mới ở .NET và tôi quyết định giải quyết .NET Core thay vì học "những cách cũ". Tôi đã tìm thấy một bài viết chi tiết về việc thiết lập AutoMapper cho .NET Core ở đây , nhưng có một hướng dẫn đơn giản hơn cho người mới không?
Câu trả lời:
Tôi đã hiểu rồi! Dưới đây là chi tiết:
Thêm gói tiêm phụ thuộc AutoMapper vào giải pháp của bạn thông qua NuGet .
Tạo một lớp mới cho một hồ sơ ánh xạ. (Tôi đã tạo một lớp trong thư mục giải pháp chính được gọi MappingProfile.cs
và thêm mã sau đây.) Tôi sẽ sử dụng một User
và UserDto
đối tượng làm ví dụ.
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>();
}
}
Sau đó thêm AutoMapperConfiguration vào Startup.cs
như dưới đây:
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();
}
Để gọi đối tượng được ánh xạ trong mã, hãy làm như sau:
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!
}
}
Tôi hy vọng điều này sẽ giúp ai đó bắt đầu mới với ASP.NET Core! Tôi hoan nghênh mọi phản hồi hoặc chỉ trích vì tôi vẫn chưa quen với thế giới .NET!
Profile
các lớp học được định vị
Bước để sử dụng AutoMapper với ASP.NET Core.
Bước 1. Cài đặt AutoMapper.Extensions.Microsoft.DependencyInjection từ Gói NuGet.
Bước 2. Tạo một Thư mục trong Giải pháp để giữ các ánh xạ với Tên "Ánh xạ".
Bước 3. Sau khi thêm thư mục Ánh xạ, chúng tôi đã thêm một lớp có Tên " MappingProfile ", tên này có thể là bất cứ điều gì độc đáo và tốt để hiểu.
Trong lớp học này, chúng tôi sẽ duy trì tất cả các ánh xạ.
Bước 4. Khởi tạo Mapper khi khởi động "ConfigureService"
Trong Lớp Khởi động, chúng tôi cần Khởi tạo Hồ sơ mà chúng tôi đã tạo và Đăng ký Dịch vụ AutoMapper.
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
Đoạn mã để hiển thị Phương thức ConfigureService nơi chúng tôi cần Khởi tạo và Đăng ký 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);
}}
Bước 5. Nhận đầu ra.
Để có được kết quả đã ánh xạ, chúng ta cần gọi AutoMapper.Mapper.Map và vượt qua Điểm đến và Nguồn thích hợp.
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'
. Tôi đang sử dụng AutoMapper.Extensions.Microsoft.DependencyInjection
phiên bản 7.0.0
Tôi muốn mở rộng câu trả lời của @ theutz - cụ thể là dòng này:
// services.AddAutoMapper(typeof(Startup)); // <-- newer automapper version uses this signature.
Có một lỗi ( có thể ) trong AutoMapper.Extensions.Microsoft.DependencyInjection phiên bản 3.2.0. (Tôi đang sử dụng .NET Core 2.0)
Này được giải quyết trong này vấn đề GitHub. Nếu các lớp của bạn kế thừa lớp Hồ sơ của AutoMapper tồn tại bên ngoài hội đồng nơi lớp Khởi động của bạn có thể sẽ không được đăng ký nếu phép tiêm AutoMapper của bạn trông như thế này:
services.AddAutoMapper();
trừ khi bạn chỉ định rõ ràng tập hợp nào để tìm kiếm cấu hình AutoMapper.
Nó có thể được thực hiện như thế này trong Startup.ConfigureService của bạn:
services.AddAutoMapper(<assembies> or <type_in_assemblies>);
trong đó "hội đồng" và "type_in_assemblies" trỏ đến hội đồng nơi các lớp Hồ sơ trong ứng dụng của bạn được chỉ định. Ví dụ:
services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));
Tôi cho rằng (và tôi nhấn mạnh vào từ này) rằng do việc thực hiện quá tải không tham số (mã nguồn từ GitHub ):
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
}
chúng tôi dựa vào CLR đã lắp ráp JITed có chứa các cấu hình AutoMapper có thể đúng hoặc có thể không đúng vì chúng chỉ được ghi chú khi cần (chi tiết hơn trong câu hỏi StackOverflow này ).
Câu trả lời của theutz ở đây rất hay, tôi chỉ muốn thêm điều này:
Nếu bạn để hồ sơ ánh xạ kế thừa từ MapperConfigurationExpression
thay vì Profile
, bạn có thể chỉ cần thêm một bài kiểm tra để xác minh thiết lập ánh xạ của mình, điều này luôn tiện dụng:
[Fact]
public void MappingProfile_VerifyMappings()
{
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(mappingProfile);
var mapper = new Mapper(config);
(mapper as IMapper).ConfigurationProvider.AssertConfigurationIsValid();
}
Tôi đã giải quyết nó theo cách này (tương tự như trên nhưng tôi cảm thấy đó là một giải pháp sạch hơn) cho .NET Core 2.2 / Automapper 8.1.1 w / Tiện ích mở rộng.DI 6.1.1.
Tạo lớp MappingProfile.cs và điền vào hàm tạo với Bản đồ (Tôi dự định sử dụng một lớp duy nhất để giữ tất cả ánh xạ của mình)
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Source, Dest>().ReverseMap();
}
}
Trong Startup.cs, hãy thêm vào bên dưới để thêm vào DI (đối số lắp ráp dành cho lớp chứa các cấu hình ánh xạ của bạn, trong trường hợp của tôi, đó là lớp MappingProfile).
//add automapper DI
services.AddAutoMapper(typeof(MappingProfile));
Trong Trình điều khiển, sử dụng nó giống như bất kỳ đối tượng DI nào khác
[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);
}
}
MappingProfiles
với new Type[]{}
như trong câu trả lời này là không cần thiết.
Trong Startup.cs của tôi (Core 2.2, Automapper 8.1.1)
services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
Trong dự án truy cập dữ liệu của tôi
namespace DAL
{
public class MapperProfile : Profile
{
// place holder for AddAutoMapper (to bring in the DAL assembly)
}
}
Trong định nghĩa mô hình của tôi
namespace DAL.Models
{
public class PositionProfile : Profile
{
public PositionProfile()
{
CreateMap<Position, PositionDto_v1>();
}
}
public class Position
{
...
}
services.AddAutoMapper( typeof(DAL.MapperProfile) );
thay vì services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
?
Tôi thích rất nhiều câu trả lời, đặc biệt là câu trả lời của @saineshwar. Tôi đang sử dụng .net Core 3.0 với AutoMapper 9.0, vì vậy tôi cảm thấy đã đến lúc cập nhật câu trả lời của mình.
Điều làm việc cho tôi là trong Startup.ConfigureService (...) đăng ký dịch vụ theo cách này:
services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>(),
AppDomain.CurrentDomain.GetAssemblies());
Tôi nghĩ rằng phần còn lại của câu trả lời @saineshwar giữ cho hoàn hảo. Nhưng nếu có ai quan tâm mã điều khiển của tôi là:
[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);
}
Và lớp ánh xạ của tôi:
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();
}
}
----- BIÊN TẬP -----
Sau khi đọc các tài liệu được liên kết trong các bình luận của Lucian Bargaoanu, tôi nghĩ tốt hơn nên thay đổi câu trả lời này một chút.
Không tham số services.AddAutoMapper()
(có câu trả lời @saineshwar) không hoạt động nữa (ít nhất là đối với tôi). Nhưng nếu bạn sử dụng bộ lắp ráp NuGet AutoMapper.Extensions.Microsoft.DependencyInjection, khung có thể kiểm tra tất cả các lớp mở rộng AutoMapper.Profile (như của tôi, MappingProfile).
Vì vậy, trong trường hợp của tôi, khi lớp thuộc cùng một tổ hợp thực thi, việc đăng ký dịch vụ có thể được rút ngắn thành services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(Một cách tiếp cận thanh lịch hơn có thể là một phần mở rộng không tham số với mã hóa này).
Cảm ơn, Lucian!
Tôi đang sử dụng AutoMapper 6.1.1 và asp.net Core 1.1.2.
Trước hết, định nghĩa các lớp Hồ sơ được kế thừa bởi Lớp Hồ sơ của Máy tự động. Tôi đã tạo giao diện IProfile trống, mục đích chỉ là tìm các lớp thuộc loại này.
public class UserProfile : Profile, IProfile
{
public UserProfile()
{
CreateMap<User, UserModel>();
CreateMap<UserModel, User>();
}
}
Bây giờ tạo một lớp riêng, ví dụ: Ánh xạ
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
});
}
}
}
}
Bây giờ trong Dự án web MVC Core trong tệp Startup.cs, trong hàm tạo, hãy gọi lớp Ánh xạ sẽ khởi tạo tất cả ánh xạ tại thời điểm tải ứng dụng.
Mappings.RegisterMappings();
Đối với ASP.NET Core (được thử nghiệm bằng 2.0+ và 3.0), nếu bạn muốn đọc tài liệu nguồn: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md
Mặt khác, làm theo 4 bước sau:
Cài đặt AutoMapper.Extensions.Microsoft.DependancyInjection từ nuget.
Đơn giản chỉ cần thêm một số lớp hồ sơ.
Sau đó thêm bên dưới vào lớp startup.cs của bạn.
services.AddAutoMapper(OneOfYourProfileClassNamesHere)
Sau đó, chỉ cần tiêm IMapper trong bộ điều khiển của bạn hoặc bất cứ nơi nào bạn cần:
public class EmployeesController {
private readonly IMapper _mapper;
public EmployeesController(IMapper mapper){
_mapper = mapper;
}
Và nếu bạn muốn sử dụng ProjectTo thì bây giờ chỉ cần:
var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync()
Đối với 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)
}
}
Trong khởi nghiệp của bạn:
services.AddAutoMapper(GetAutoMapperProfilesFromAllAssemblies()
.ToArray());
Trong Bộ điều khiển hoặc dịch vụ: Tiêm mapper:
private readonly IMapper _mapper;
Sử dụng:
var obj = _mapper.Map<TDest>(sourceObject);
Để thêm vào những gì Arve Systad đã đề cập để thử nghiệm. Nếu vì bất kỳ lý do gì bạn thích tôi và muốn duy trì cấu trúc thừa kế được cung cấp trong giải pháp theutz, bạn có thể thiết lập MapperConfiguration như vậy:
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(mappingProfile);
});
var mapper = new Mapper(config);
Tôi đã làm điều này trong NUnit.
dịch vụ.AddAutoMapper (); không làm việc cho tôi. (Tôi đang sử dụng Asp.Net Core 2.0)
Sau khi cấu hình như dưới đây
var config = new AutoMapper.MapperConfiguration(cfg =>
{
cfg.CreateMap<ClientCustomer, Models.Customer>();
});
khởi tạo trình ánh xạ IMapper mapper = config.CreateMapper ();
và thêm đối tượng mapper vào các dịch vụ dưới dạng dịch vụ singleton.AddSingleton (mapper);
bằng cách này tôi có thể thêm DI vào bộ điều khiển
private IMapper autoMapper = null;
public VerifyController(IMapper mapper)
{
autoMapper = mapper;
}
và tôi đã sử dụng như dưới đây trong các phương pháp hành động của mình
ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
về câu trả lời của theutz, không cần chỉ định parrameter ánh xạ IMapper tại hàm tạo của bộ điều khiển.
bạn có thể sử dụng Mapper vì nó là thành viên tĩnh tại bất kỳ vị trí nào của mã.
public class UserController : Controller {
public someMethod()
{
Mapper.Map<User, UserDto>(user);
}
}
IMapper
bạn có thể chế nhạo nó và, ví dụ, chỉ cần làm cho nó trở về null nếu nó không liên quan đến thử nghiệm đã cho.