.NET'te nispeten yeniyim ve "eski yolları" öğrenmek yerine .NET Core ile uğraşmaya karar verdim. Burada .NET Core için AutoMapper kurulumu hakkında ayrıntılı bir makale buldum , ancak bir acemi için daha basit bir yol var mı?
.NET'te nispeten yeniyim ve "eski yolları" öğrenmek yerine .NET Core ile uğraşmaya karar verdim. Burada .NET Core için AutoMapper kurulumu hakkında ayrıntılı bir makale buldum , ancak bir acemi için daha basit bir yol var mı?
Yanıtlar:
Bunu anladım! Ayrıntılar:
Aracılığıyla çözüme AutoMapper Bağımlılık Enjeksiyon Paketi ekle Nuget .
Bir eşleme profili için yeni bir sınıf oluşturun. (Ana çözüm dizininde bir sınıf yaptım MappingProfile.cs
ve aşağıdaki kodu ekledim.) Örnek olarak bir User
ve UserDto
nesnesi kullanacağım .
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>();
}
}
Ardından AutoMapperConfiguration'ı Startup.cs
aşağıda gösterildiği gibi ekleyin :
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();
}
Eşlenen nesneyi kodda çağırmak için aşağıdakine benzer bir şey yapın:
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!
}
}
Umarım bu ASP.NET Core ile yeni başlayan birine yardımcı olur! .NET dünyasında hala yeni olduğum için herhangi bir geri bildirimi veya eleştiriyi memnuniyetle karşılıyoruz!
Profile
sınıfların nasıl bulunduğunu açıklıyor
ASP.NET Core ile AutoMapper Kullanımı Adım.
Adım 1. NuGet Paketinden AutoMapper.Extensions.Microsoft.DependencyInjection uygulamasını kurma.
Adım 2. "Eşlemeler" Adlı Eşlemeleri tutmak için Çözümde bir Klasör oluşturun.
Adım 3. Eşleme klasörü ekledikten sonra " MappingProfile " adında bir sınıf ekledik, bu ad benzersiz ve anlaşılması iyi bir şey olabilir.
Bu sınıfta, tüm eşlemeleri koruyacağız.
Adım 4. "ConfigureServices" Başlangıçta Eşleştiriciyi Başlatma
Başlangıç Sınıfında, oluşturduğumuz Profili Başlatmamız ve AutoMapper Hizmetini Kaydetmemiz Gerekir.
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
AutoMapper'ı başlatmamız ve kaydetmemiz gereken ConfigureServices Yöntemini göstermek için Kod Parçacığı.
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);
}}
Adım 5. Çıktı Al.
Eşlenmiş sonucu almak için AutoMapper.Mapper.Map'i çağırmalı ve Doğru Hedef ve Kaynağı geçmeliyiz.
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 sürümünü kullanıyorum
@ Theutz'un cevaplarını uzatmak istiyorum - yani bu satır:
// services.AddAutoMapper(typeof(Startup)); // <-- newer automapper version uses this signature.
AutoMapper.Extensions.Microsoft.DependencyInjection sürüm 3.2.0'da bir hata ( muhtemelen ) var. (.NET Core 2.0 kullanıyorum)
Bu baş ettiğini bu GitHub konuda. AutoMapper'in Profile sınıfını devralan sınıflarınız, Startup sınıfını oluşturduğunuz montajın dışındaysa, AutoMapper enjeksiyonunuz şöyle görünüyorsa muhtemelen kaydedilmeyecektir:
services.AddAutoMapper();
hangi derlemeleri AutoMapper profillerinde arayacağınızı açıkça belirtmediğiniz sürece.
Startup.ConfigureServices öğenizde şu şekilde yapılabilir:
services.AddAutoMapper(<assembies> or <type_in_assemblies>);
burada "montajlar" ve "type_in_assemblies" , uygulamanızdaki Profil sınıflarının belirtildiği montajı gösterir. Örneğin:
services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));
Ben varsayalım (ve bu kelimeye vurgu) olduğu nedeniyle parametresiz aşırı (kaynak kodu uygulanmasını takip etmek GitHub'dan ):
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
}
AutoMapper profillerini içeren JITed derlemesine sahip olan ve yalnızca gerektiğinde kesilebileceği için doğru olabilecek veya olmayabilecek CLR'ye güveniyoruz ( bu StackOverflow sorusunda daha fazla ayrıntı ).
theutz'un cevabı çok iyi, sadece bunu eklemek istiyorum:
Eşleme profilinizin MapperConfigurationExpression
bunun yerine miras almasına izin Profile
verirseniz, eşleme kurulumunuzu doğrulamak için her zaman kullanışlı olan bir test ekleyebilirsiniz:
[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 / Extensions için bu şekilde çözdüm (yukarıdakine benzer ama daha temiz bir çözüm gibi hissediyorum).
MappingProfile.cs sınıfı oluşturun ve yapıcıyı Haritalar ile doldurun (Tüm eşlemelerimi tutmak için tek bir sınıf kullanmayı planlıyorum)
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Source, Dest>().ReverseMap();
}
}
Startup.cs içinde, DI'ye eklemek için aşağı ekleyin (montaj argümanı, eşleme yapılandırmalarınızı tutan sınıf içindir, benim durumumda MappingProfile sınıfıdır).
//add automapper DI
services.AddAutoMapper(typeof(MappingProfile));
Denetleyici'de bunu diğer DI nesnelerinde yaptığınız gibi kullanın
[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
ile new Type[]{}
gösterildiği gibi bu cevap gereksizdir.
Startup.cs dosyamda (Core 2.2, Automapper 8.1.1)
services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
Veri erişim projemde
namespace DAL
{
public class MapperProfile : Profile
{
// place holder for AddAutoMapper (to bring in the DAL assembly)
}
}
Model tanımımda
namespace DAL.Models
{
public class PositionProfile : Profile
{
public PositionProfile()
{
CreateMap<Position, PositionDto_v1>();
}
}
public class Position
{
...
}
services.AddAutoMapper( typeof(DAL.MapperProfile) );
yerine services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
?
Birçok cevabı severim, özellikle @saineshwar'ın cevabı. AutoMapper 9.0 ile .net Core 3.0 kullanıyorum, bu yüzden cevabını güncelleme zamanı geldiğini hissediyorum.
Benim için işe yarayan Startup.ConfigureServices (...) hizmetini şu şekilde kaydettirdi:
services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>(),
AppDomain.CurrentDomain.GetAssemblies());
@Saineshwar cevabının geri kalanının mükemmel olduğunu düşünüyorum. Ama kimse ilgileniyorsa benim denetleyici kodu:
[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);
}
Ve benim harita sınıfım:
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();
}
}
----- DÜZENLE -----
Lucian Bargaoanu'nun yorumlarında yer alan dokümanları okuduktan sonra, bu cevabı biraz değiştirmek daha iyi olduğunu düşünüyorum.
Parametresiz services.AddAutoMapper()
(@saineshwar cevabı vardı) artık çalışmıyor (en azından benim için). Ancak NuGet derlemesi AutoMapper.Extensions.Microsoft.DependencyInjection kullanırsanız, çerçeve AutoMapper.Profile dosyasını (benimki gibi MappingProfile gibi) genişleten tüm sınıfları denetleyebilir.
Yani, benim durumumda, sınıfın aynı yürütme derlemesine ait olduğu durumda, hizmet kaydı kısaltılabilir services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(Daha zarif bir yaklaşım, bu kodlama ile parametresiz bir uzantı olabilir).
Teşekkürler Lucian!
AutoMapper 6.1.1 ve asp.net Core 1.1.2 kullanıyorum.
Her şeyden önce, Automapper'ın Profile Class tarafından miras alınan Profile sınıflarını tanımlayın. Boş olan IProfile arabirimini oluşturdum, amacı sadece bu tür sınıfları bulmak.
public class UserProfile : Profile, IProfile
{
public UserProfile()
{
CreateMap<User, UserModel>();
CreateMap<UserModel, User>();
}
}
Şimdi ayrı bir sınıf oluşturun, örneğin Mappings
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
});
}
}
}
}
Şimdi Startup.cs dosyasındaki MVC Core web Project'te, yapıcıda, uygulama yükleme sırasında tüm eşlemeleri başlatan Mapping sınıfını çağırın.
Mappings.RegisterMappings();
ASP.NET Core için (2.0+ ve 3.0 kullanılarak test edilmiştir), kaynak belgeleri okumayı tercih ederseniz: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md
Aksi takdirde bu 4 adımı takip etmek işe yarar:
Nuget'ten AutoMapper.Extensions.Microsoft.DependancyInjection uygulamasını yükleyin.
Sadece bazı profil sınıfları ekleyin.
Ardından startup.cs sınıfınıza ekleyin.
services.AddAutoMapper(OneOfYourProfileClassNamesHere)
Ardından, kontrol cihazlarınıza veya ihtiyacınız olan yere IMapper'ı enjekte edin:
public class EmployeesController {
private readonly IMapper _mapper;
public EmployeesController(IMapper mapper){
_mapper = mapper;
}
Ve ProjectTo şimdi kullanmak istiyorsanız:
var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync()
AutoMapper 9.0.0 için:
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)
}
}
Startup'ınızda:
services.AddAutoMapper(GetAutoMapperProfilesFromAllAssemblies()
.ToArray());
Denetleyici veya hizmette: Eşleştiriciyi enjekte et:
private readonly IMapper _mapper;
Kullanımı:
var obj = _mapper.Map<TDest>(sourceObject);
Test için Arve Systad'ın bahsettiklerini eklemek için. Herhangi bir nedenden dolayı benim gibi olursanız ve theutz çözümünde sağlanan kalıtım yapısını korumak istiyorsanız, MapperConfiguration'ı şu şekilde ayarlayabilirsiniz:
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(mappingProfile);
});
var mapper = new Mapper(config);
Bunu NUnit'te yaptım.
services.AddAutoMapper (); benim için çalışmadı. (Asp.Net Core 2.0 kullanıyorum)
Aşağıdaki gibi yapılandırdıktan sonra
var config = new AutoMapper.MapperConfiguration(cfg =>
{
cfg.CreateMap<ClientCustomer, Models.Customer>();
});
mapper'ı başlat IMapper mapper = config.CreateMapper ();
ve eşleştirici nesnesini tek bir hizmet olarak hizmetlere ekleyin.
bu şekilde denetleyiciye bir DI ekleyebiliyorum
private IMapper autoMapper = null;
public VerifyController(IMapper mapper)
{
autoMapper = mapper;
}
ve eylem yöntemlerimde aşağıdaki gibi kullandım
ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
theutz cevabı hakkında , kontrolör yapıcısında IMapper eşleyici parrametresini belirtmeye gerek yoktur .
Mapper'ı, kodun herhangi bir yerinde statik bir üye olduğu için kullanabilirsiniz.
public class UserController : Controller {
public someMethod()
{
Mapper.Map<User, UserDto>(user);
}
}
IMapper
bunu alay edebilir ve örneğin, verilen test için ilgisizse null değerini döndürmesini sağlayabilirsiniz.