در پست قبلی مقدمهای داشتیم بر AutoMapper؛ مثالی که در اون پست عنوان شد سادهترین و پرکاربردترین روش استفاده از AutoMapper هست بنام Flattening که در واقع از یک شیء کل به یک شیء کوچکتر میرسیم.
همانطور که در قسمت اول گفتم AutoMapper کارش رو بر اساس قراردادها انجام میده یا همون Convention Base. یکی از قردادهای AutoMapper، نگاشت براساس نام اعضای اون شی هست؛ مثلا در مثال قبلی FirstName در مبداء، به خاصیتی با همین نام نگاشت شد و ...
Projection
روش استفاده بعدی که به اون Projection (معنی فارسی خوب برا Projection چیه ؟) میگن برای مواقعی هست که اعضای یک شیء در مبداء، همتایی در مقصد ندارد (از نظر نام) و در واقع میخواهیم یک شیء رو به یک شیء دیگه تغییر شکل بدیم.
مدل زیر رو در نظر بگیرید:
که قرار است به مدل PersonDTO نگاشت بشه.
همنطور که میبینید در مقصد خاصیتهایی داریم که در مبداء همتایی ندارند. برای نگاشت چنین اشیایی، از متد ForMember استفاده و نگاشتهای شیهای موردنظر رو Custom میکنیم.
متد ForMember از یک Action Delegate برای کانفیگ کردن هر عضو استفاده میکنه. در مثال بالا ما از MapFrom برای اعمال نگاشت Custom استفاده کردیم.
نکته:برای تست کردن اینکه آیا نگاشت ما Exception داره یا نه میتوان از متد زیر استفاده کرد.
نکته: همیشه موقع نگاشت، اعضای شیء مقصد برای AutoMapper مهمن؛ مثلا در مثال بالا خاصیت LastName در مبداء به هیچ عضوی در مقصد نگاشت نشده (به صورت مستقیم) و این تولید Exception نمیکنه ولی برعکس اون باعث تولید Exception میشه؛ مثلا اگه خاصیت Email رو که در مبداء همتایی نداره رو کانفیگ نکنیم، باعث تولید Exception میشه.
نحوه استفاده
خروجی به شکل زیر میشه
Collection
بعد از نوشتن کانفیگ نگاشتها، بدون نیاز به تنظیمات خاصی میتونیم مجموعه ای از شیهای مبداء رو به مقصد نگاشت کنیم. مجموعههای پشتیبانی شده به شرح زیرن.
و البته آرایه ها.
مثال
خروجی به شکل زیر میشه
Nested Mappings
برای نگاشت کلاسهای تو در تو از این روش استفاده میکنیم و ...
فرض کنید در کلاس Person خاصیتی از نوع Address داریم و در کلاس PersonDTO خاصیتی از نوع AddressDTO.
برای نگاشتهایی از این دست باید تنظیمات نگاشت مربوط به نوعهای تودرتو را صریحا معین کنیم.
نکته: هرچند منطقیتر بنظر میرسه که تعریف نگاشتهای داخلی ابتدا بیاد، ولی فرقی نمیکنه که تعریف این نگاشت قبل یا بعد از نگاشت اصلی باشه.
ادامه دارد...
همانطور که در قسمت اول گفتم AutoMapper کارش رو بر اساس قراردادها انجام میده یا همون Convention Base. یکی از قردادهای AutoMapper، نگاشت براساس نام اعضای اون شی هست؛ مثلا در مثال قبلی FirstName در مبداء، به خاصیتی با همین نام نگاشت شد و ...
Projection
روش استفاده بعدی که به اون Projection (معنی فارسی خوب برا Projection چیه ؟) میگن برای مواقعی هست که اعضای یک شیء در مبداء، همتایی در مقصد ندارد (از نظر نام) و در واقع میخواهیم یک شیء رو به یک شیء دیگه تغییر شکل بدیم.
مدل زیر رو در نظر بگیرید:
public class Person { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
که قرار است به مدل PersonDTO نگاشت بشه.
public class PersonDTO { public int Id { get; set; } public string Name { get; set; } public string Family { get; set; } public string FullName { get; set; } public string Email { get; set; } }
Mapper.CreateMap<Person, PersonDTO>().ForMember(des => des.Name, op => op.MapFrom(src => src.FirstName)). ForMember(des => des.FullName, op => op.MapFrom(src => src.FirstName + " " + src.LastName)).ForMember( des => des.Email, op => op.Ignore());
AutoMapper.IMappingExpression<TSource,TDestination>.ForMember(System.Linq.Expressions.Expression<System.Func<TDestination,object>>, System.Action<AutoMapper.IMemberConfigurationExpression<TSource>>)
نکته:برای تست کردن اینکه آیا نگاشت ما Exception داره یا نه میتوان از متد زیر استفاده کرد.
Mapper.AssertConfigurationIsValid();
نکته: همیشه موقع نگاشت، اعضای شیء مقصد برای AutoMapper مهمن؛ مثلا در مثال بالا خاصیت LastName در مبداء به هیچ عضوی در مقصد نگاشت نشده (به صورت مستقیم) و این تولید Exception نمیکنه ولی برعکس اون باعث تولید Exception میشه؛ مثلا اگه خاصیت Email رو که در مبداء همتایی نداره رو کانفیگ نکنیم، باعث تولید Exception میشه.
نحوه استفاده
var person = new Person { Id = 1, FirstName = "Mohammad", LastName = "Saheb", }; var personDTO = Mapper.Map<Person, PersonDTO>(person);
Collection
بعد از نوشتن کانفیگ نگاشتها، بدون نیاز به تنظیمات خاصی میتونیم مجموعه ای از شیهای مبداء رو به مقصد نگاشت کنیم. مجموعههای پشتیبانی شده به شرح زیرن.
IEnumerable, IEnumerable<T>, ICollection, ICollection<T>, IList, IList<T>, List<T>.
مثال
var persons = new[] { new Person { Id = 1, FirstName = "Mohammad", LastName = "Saheb" }, new Person { Id = 2, FirstName = "Babak", LastName = "Saheb" } }; var personDTOs = Mapper.Map<Person[], List<PersonDTO>>(persons);
Nested Mappings
برای نگاشت کلاسهای تو در تو از این روش استفاده میکنیم و ...
فرض کنید در کلاس Person خاصیتی از نوع Address داریم و در کلاس PersonDTO خاصیتی از نوع AddressDTO.
public class Address { public string Ad1 { get; set; } public string Ad2 { get; set; } } public class AddressDTO { public string Ad1 { get; set; } public string Ad2 { get; set; } }
Mapper.CreateMap<Address, AddressDTO>();
ادامه دارد...