اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
سه دقیقه
نگاشت اشیاء امری مفید و لذت بخش است. ولی بخاطر تنظیمات خاص آن و افزایش کدها، همیشه کمی دردسر ساز بوده است. استفاده از کلاس Profile راه کار مناسبی است؛ اما در این حالت کلاس مقصد (ViewModel) از تنظیمات نگاشتها بی اطلاع میماند و فقط حاوی داده خواهد بود. برای ادغام کلاس و تنظیمات نگاشت در اینجا راهکاری ارائه گردید که در ادامه و با الگو گیری از همین ایده، اقدام به ارائهی روشی جدید میکنم که با استفاده از Attributeها تنظیمات نگاشت اشیاء را در AutoMapper انجام میدهد.
در نهایت میخواهیم نگاشتها را اینچنین تنظیم کنیم:
این سبک تنظیم کردن نگاشتهای اشیاء به نظر بهتر از روشهای دیگر است؛ چون کلاسهای ویوومدل را معنادار کرده و همچنین برای برنامه نویسان EF و ASP.NET MVC استفادهی از ویژگیها، یک شیوهی کاری معمول به حساب میآید.
به تعریف و توضیح صفتهای (ویژگیها یا Attributes) مورد نیاز میپردازم:
صفت MapFromAttribute
این صفت روی کلاسها مینشیند و توسط آرگومان sourceType آن، نوع مبدأ را برای automapper مشخص میکند. در واقع همه چیز از اینجا شروع میشود. همچنین آرگومان ignoreAllNonExistingProperty مشخص میکند کلیهی صفاتی که در مقصد هستند ولی معادل اسمی در مبدأ ندارند، بصورت خودکار رد (Ignore) شده و از آنها صرف نظر شود تا از شکست متد AutoMapper.Mapper.AssertConfigurationIsValid جلوگیری کند (پرداخته شده در اینجا). آرگومان alsoCopyMetadata پیاده سازی نمیشود؛ ولی میتواند پرچمی باشد تا اجازه دهد Data Annotations از مدلهای ef به ViewModel انتقال یابند.
صفت IgnoreMapAttribute
از این صفت برای رد کردن خصیصهای در نگاشتها استفاده میکنیم. لازم به ذکر است که صفتی مشابه در Automapper.IgnoreAttribute وجود دارد که میتواند به جای این صفت مورد استفاده قرار گیرد. «نگارنده جهت همخوانی با سایر صفات، اقدام به استفادهی از این صفت میکند»
صفت MapForMemberAttribute
اگر نام خصیصهها در مبدأ و مقصد یکی نباشند، از این صفت برای همگام سازی این دو استفاده میکنیم.
صفت UseValueResolverAttribute
استفاده از ValueResolverها در اینجا ذکر شده است. از این صفت برای تنظیم این مقدار برای یک خصیصه استفاده میشود. برای مثال فیلد FullName را در مقصد درنظر بگیرد که از دو فیلد Name و Family در مبدأ تشکیل میشود.
تا اینجا صفات پیش نیاز کار فراهم شدند. حال باید این صفتها را به نگاشت متناسبی در automapper تبدیل کنیم.
دریافت کدها
ادامه دارد...
در نهایت میخواهیم نگاشتها را اینچنین تنظیم کنیم:
[MapFrom(typeof (Student), ignoreAllNonExistingProperty: true, alsoCopyMetadata: true)] public class AdminStudentViewModel { // [IgnoreMap] public int Id { set; get; } [MapForMember("Name")] public string FirstName { set; get; } [MapForMember("Family")] public string LastName { set; get; } public string Email { set; get; } [MapForMember("RegisterDateTime")] public string RegisterDateTimePersian { set; get; } [UseValueResolver(typeof (BookCountValueResolver))] public int BookCounts { set; get; } [UseValueResolver(typeof (BookPriceValueResolver))] public decimal BookPrice { set; get; } };
به تعریف و توضیح صفتهای (ویژگیها یا Attributes) مورد نیاز میپردازم:
صفت MapFromAttribute
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class MapFromAttribute : Attribute { public Type SourceType { get; private set; } public bool IgnoreAllNonExistingProperty { get; private set; } public bool AlsoCopyMetadata { get; private set; } //Go to: https://www.dntips.ir/courses/topic/16/cb36bc2e-4263-431e-86a5-236322cb5576 public MapFromAttribute(Type sourceType, bool ignoreAllNonExistingProperty = false, bool alsoCopyMetadata = false) { SourceType = sourceType; IgnoreAllNonExistingProperty = ignoreAllNonExistingProperty; AlsoCopyMetadata = alsoCopyMetadata; } };
صفت IgnoreMapAttribute
[AttributeUsage(AttributeTargets.Property)] public class IgnoreMapAttribute : Attribute {};
صفت MapForMemberAttribute
[AttributeUsage(AttributeTargets.Property)] public class MapForMemberAttribute : Attribute { public string MemberToMap { get; private set; } public MapForMemberAttribute(string memberToMap) { MemberToMap = memberToMap; } };
صفت UseValueResolverAttribute
[AttributeUsage(AttributeTargets.Property)] public class UseValueResolverAttribute : Attribute { public IValueResolver ValueResolver { get; private set; } public UseValueResolverAttribute(Type valueResolver) { ValueResolver = valueResolver.GetConstructors()[0].Invoke(new object[] {}) as IValueResolver; } };
تا اینجا صفات پیش نیاز کار فراهم شدند. حال باید این صفتها را به نگاشت متناسبی در automapper تبدیل کنیم.
دریافت کدها
ادامه دارد...