मैं .NET पर अपेक्षाकृत नया हूं, और मैंने "पुराने तरीके" सीखने के बजाय .NET कोर से निपटने का फैसला किया है। मैंने यहां .NET कोर के लिए AutoMapper स्थापित करने के बारे में एक विस्तृत लेख पाया , लेकिन क्या एक नौसिखिया के लिए अधिक सरल पूर्वाभ्यास है?
मैं .NET पर अपेक्षाकृत नया हूं, और मैंने "पुराने तरीके" सीखने के बजाय .NET कोर से निपटने का फैसला किया है। मैंने यहां .NET कोर के लिए AutoMapper स्थापित करने के बारे में एक विस्तृत लेख पाया , लेकिन क्या एक नौसिखिया के लिए अधिक सरल पूर्वाभ्यास है?
जवाबों:
मैं यह समझ गया! यहाँ विवरण है:
NuGet के माध्यम से अपने समाधान के लिए AutoMapper निर्भरता इंजेक्शन पैकेज जोड़ें ।
मैपिंग प्रोफ़ाइल के लिए एक नया वर्ग बनाएं। (मैंने मुख्य समाधान निर्देशिका में एक वर्ग बनाया जिसे बुलाया गया है MappingProfile.cs
और निम्नलिखित कोड जोड़ें।) मैं उदाहरण के रूप में एक 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>();
}
}
फिर Startup.cs
नीचे दिखाए अनुसार AutoMapperConfiguration जोड़ें :
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 कोर के साथ नए सिरे से शुरू करने में मदद करता है! मैं किसी भी प्रतिक्रिया या आलोचना का स्वागत करता हूं क्योंकि मैं अभी भी .NET दुनिया में नया हूं!
Profile
कक्षाएं स्थित हैं
ASP.NET कोर के साथ AutoMapper का उपयोग करने के लिए कदम।
चरण 1। AutoGapper.Extensions.Microsoft.D dependencyInjection को NuGet पैकेज से इंस्टॉल करना।
चरण 2. नाम "मैपिंग" के साथ मैपिंग रखने के लिए समाधान में एक फ़ोल्डर बनाएं।
स्टेप 3. मैपिंग फोल्डर को जोड़ने के बाद हमने " MappingProfile " नाम के साथ एक क्लास जोड़ा है। यह नाम समझने में कुछ भी अनोखा और अच्छा हो सकता है।
इस वर्ग में, हम सभी मैपिंग को बनाए रखने जा रहे हैं।
चरण 4। स्टार्टअप में कॉन्फ़िगर मैपर "कॉन्फ़िगर करें सेवाओं"
स्टार्टअप क्लास में, हमें प्रोफाइल को इनिशियलाइज़ करने की आवश्यकता है जिसे हमने बनाया है और ऑटोमैपर सर्विस को रजिस्टर भी किया है।
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
कॉन्फ़िगर करने की विधि को दिखाने के लिए कोड स्निपेट जहां हमें ऑटोमैपर को इनिशियलाइज़ और रजिस्टर करने की आवश्यकता होती है।
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);
सांकेतिक टुकड़ा
[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
संस्करण
मैं @utz के उत्तर का विस्तार करना चाहता हूं - अर्थात् यह पंक्ति:
// services.AddAutoMapper(typeof(Startup)); // <-- newer automapper version uses this signature.
AutoMapper.Extensions.Microsoft.D dependencyInjection संस्करण 3.2.0 में एक बग ( शायद ) है। (मैं .NET कोर 2.0 का उपयोग कर रहा हूं)
यह इस GitHub मुद्दे में निपटा है। यदि आपकी कक्षाएं AutoMapper के प्रोफ़ाइल वर्ग से बाहर निकली हुई हैं, तो आप असेंबली के बाहर मौजूद हैं जहाँ आप Startup क्लास हैं, तो वे संभवत: पंजीकृत नहीं होंगे यदि आपका AutoMapper इंजेक्शन इस तरह दिखता है:
services.AddAutoMapper();
जब तक आप स्पष्ट रूप से निर्दिष्ट नहीं करते हैं कि कौन सी असेंबलियों के लिए AutoMapper प्रोफाइल खोजना है।
यह आपके स्टार्टअप में इस तरह से किया जा सकता है। ConfigureServices:
services.AddAutoMapper(<assembies> or <type_in_assemblies>);
जहाँ "असेंबली" और "type_in_assemblies" असेंबली को इंगित करता है जहाँ आपके आवेदन में प्रोफ़ाइल कक्षाएं निर्दिष्ट हैं। उदाहरण के लिए:
services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));
मुझे लगता है (और मैंने इस शब्द पर जोर दिया) कि पैरामीटर रहित अधिभार के कार्यान्वयन के कारण ( गिटहब से स्रोत कोड ):
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 कोर 2.2 / ऑटोमैपर 8.1.1 w / एक्सटेंशन्स.DI 6.1.1 के लिए।
मैपिंग के साथ MappingProfile.cs वर्ग बनाएं और निर्माता को आबाद करें (मैं अपने सभी मैपिंग को रखने के लिए एकल वर्ग का उपयोग करने की योजना बनाता हूं)
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);
}
}
MappingProfiles
के साथ new Type[]{}
के रूप में में दिखाया गया है क्या यह उत्तर अनावश्यक है।
मेरे स्टार्टअप में (कोर 2.2, ऑटोमैपर 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) });
?
मुझे बहुत से उत्तर पसंद हैं, विशेष रूप से @ सनेश्वर का। मैं AutoMapper 9.0 के साथ .net Core 3.0 का उपयोग कर रहा हूं, इसलिए मुझे लगता है कि इसके उत्तर को अपडेट करने का समय आ गया है।
मेरे लिए क्या काम Startup.ConfigureServices (...) में इस तरह से रजिस्टर किया गया था:
services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>(),
AppDomain.CurrentDomain.GetAssemblies());
मुझे लगता है कि @ शेषेश्वर का उत्तर सही है। लेकिन अगर किसी को मेरी नियंत्रक कोड में दिलचस्पी है, तो:
[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();
}
}
----- EDIT -----
ल्यूसियन बरगाओनु द्वारा टिप्पणियों में जुड़े डॉक्स को पढ़ने के बाद, मुझे लगता है कि इस उत्तर को थोड़ा बदलना बेहतर है।
पैरामीटरलेस services.AddAutoMapper()
(जिसमें @ सनेश्वर जवाब था) अब काम नहीं करता (कम से कम मेरे लिए)। लेकिन अगर आप NuGet असेंबली AutoMapper.Extensions.Microsoft.D dependencyInjection का उपयोग करते हैं, तो फ्रेमवर्क उन सभी वर्गों का निरीक्षण करने में सक्षम है जो AutoMapper.Profile (जैसे मेरा, MappingProfile) का विस्तार करते हैं।
इसलिए, मेरे मामले में, जहां वर्ग एक ही निष्पादन विधानसभा से संबंधित है, सेवा पंजीकरण को छोटा किया जा सकता है services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(इस कोडिंग के साथ एक अधिक सुरुचिपूर्ण दृष्टिकोण एक पैरामीटर रहित विस्तार हो सकता है)।
धन्यवाद, लूसियन!
मैं AutoMapper 6.1.1 और asp.net Core 1.1.2 का उपयोग कर रहा हूं।
सबसे पहले, प्रोफाइल क्लास ऑफ ऑटोमैपर द्वारा विरासत में मिली प्रोफाइल कक्षाओं को परिभाषित करें। मैंने 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
});
}
}
}
}
अब स्टार्टअप में एमवीसी कोर वेब प्रोजेक्ट में, फ़ाइल में, कंस्ट्रक्टर में, मैपिंग क्लास को कॉल करें, जो एप्लिकेशन लोडिंग के समय सभी मैपिंग को इनिशियलाइज़ करेगा।
Mappings.RegisterMappings();
ASP.NET कोर के लिए (2.0+ और 3.0 का उपयोग करके परीक्षण किया गया), यदि आप स्रोत प्रलेखन पढ़ना पसंद करते हैं: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.D dependencyInjection/blob/master/README.md
अन्यथा इन 4 चरणों के बाद काम करता है:
Nuget से AutoMapper.Extensions.Microsoft.D dependancyInjection स्थापित करें।
बस कुछ प्रोफ़ाइल कक्षाएं जोड़ें।
फिर अपने स्टार्टअप के नीचे जोड़ें। वर्ग।
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());
नियंत्रक या सेवा में: इंजेक्टर मैपर:
private readonly IMapper _mapper;
उपयोग:
var obj = _mapper.Map<TDest>(sourceObject);
परीक्षण के लिए आरव सिस्टड ने जो उल्लेख किया है उस पर जोड़ने के लिए। यदि आप मेरे लिए जो भी कारण चाहते हैं, और इनट्यूज़ समाधान में दी गई विरासत संरचना को बनाए रखना चाहते हैं, तो आप 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>();
});
मैपर IMapper मैपर को इनिशियलाइज़ करें = config.CreateMapper ();
और एक सिंगलटन सेवाओं के रूप में सेवाओं के लिए मैपर ऑब्जेक्ट जोड़ें। एडिंगलिंगटन (मैपर);
इस तरह मैं कंट्रोलर में DI जोड़ने में सक्षम हूं
private IMapper autoMapper = null;
public VerifyController(IMapper mapper)
{
autoMapper = mapper;
}
और मैंने अपने एक्शन तरीकों में नीचे का उपयोग किया है
ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
आउटलुक उत्तर के बारे में, नियंत्रक निर्माणकर्ता में IMapper मैपर पैरामोटर को निर्दिष्ट करने की आवश्यकता नहीं है ।
आप मैपर का उपयोग कर सकते हैं क्योंकि यह कोड के किसी भी स्थान पर एक स्थिर सदस्य है।
public class UserController : Controller {
public someMethod()
{
Mapper.Map<User, UserDto>(user);
}
}
IMapper
आप इसका मजाक उड़ा सकते हैं और उदाहरण के लिए, यदि यह दिए गए परीक्षण के लिए अप्रासंगिक है, तो इसे शून्य कर दें।