# 🔧 Mapster - مشکلات رایج و راه‌حل‌ها > **آخرین بروزرسانی**: ۷ دی ۱۴۰۴ > **نسخه Mapster**: 7.4.0 --- ## 📋 فهرست مشکلات 1. [Protobuf Int64Value Mapping](#1-protobuf-int64value-mapping) 2. [MediatR Unit to Empty](#2-mediatr-unit-to-empty) 3. [Repeated Fields (List) Mapping](#3-repeated-fields-list-mapping) 4. [Property Name Mismatch](#4-property-name-mismatch) 5. [Nullable Types](#5-nullable-types) --- ## 1. Protobuf Int64Value Mapping ### مشکل فیلدهای `google.protobuf.Int64Value` (یا `StringValue`, `BoolValue` و غیره) که wrapper types هستند، در mapping مستقیم کار نمی‌کنند. ### نشانه‌ها - مقدار همیشه `0` یا `null` می‌شود - Value در client ست شده ولی در server نادرست دریافت می‌شود ### Proto: ```protobuf import "google/protobuf/wrappers.proto"; message GetMyWeeklyBalancesRequest { google.protobuf.Int64Value week_definition_id = 3; } ``` ### ❌ کد اشتباه: ```csharp config.NewConfig() .Map(dest => dest.WeekDefinitionId, src => src.WeekDefinitionId); // WRONG! ``` ### ✅ کد صحیح: ```csharp config.NewConfig() .Map(dest => dest.WeekDefinitionId, src => src.WeekDefinitionId != null ? src.WeekDefinitionId.Value : null); ``` ### توضیح `Int64Value` یک class wrapper است نه primitive type. باید `.Value` را extract کنید. --- ## 2. MediatR Unit to Empty ### مشکل `MediatR.Unit` نمی‌تواند به `google.protobuf.WellKnownTypes.Empty` map شود. ### نشانه‌ها - Exception: `No mapping found for MediatR.Unit` - gRPC call با void return کار نمی‌کند ### ❌ کد اشتباه: ```csharp // No mapping defined - will fail at runtime return await _mediator.Send(command).Adapt(); ``` ### ✅ راه‌حل: ```csharp // در GeneralMapping.cs یا هر Profile config.NewConfig() .MapWith(_ => new Google.Protobuf.WellKnownTypes.Empty()); ``` ### محل فایل: `BackOffice.BFF.WebApi/Common/Mappings/GeneralMapping.cs` --- ## 3. Repeated Fields (List) Mapping ### مشکل فیلدهای `repeated` در protobuf به property `RepeatedField` تبدیل می‌شوند که `add-only` هستند. ### نشانه‌ها - لیست همیشه خالی - Exception: `Cannot set RepeatedField` ### Proto: ```protobuf message GetAllAppVersionsResponse { repeated AppVersionItem items = 1; } ``` ### ❌ کد اشتباه: ```csharp config.NewConfig, GetAllAppVersionsResponse>() .Map(dest => dest.Items, src => src); // WRONG - Items is read-only ``` ### ✅ کد صحیح: ```csharp config.NewConfig, GetAllAppVersionsResponse>() .MapWith(src => CreateResponse(src)); private static GetAllAppVersionsResponse CreateResponse(List items) { var response = new GetAllAppVersionsResponse(); foreach (var item in items) { response.Items.Add(item.Adapt()); } return response; } ``` --- ## 4. Property Name Mismatch ### مشکل نام property در DTO با نام در proto message یکی نیست. ### نشانه‌ها - فیلد همیشه `null` یا default value - Auto-mapping کار نمی‌کند ### مثال: ```protobuf message MetaData { int32 total_page = 2; // -> TotalPage in C# } ``` ```csharp public class MetaDataDto { public int TotalPages { get; set; } // WRONG: should be TotalPage } ``` ### ✅ راه‌حل 1 - اصلاح نام: ```csharp public class MetaDataDto { public int TotalPage { get; set; } // Match proto } ``` ### ✅ راه‌حل 2 - Explicit mapping: ```csharp config.NewConfig() .Map(dest => dest.TotalPages, src => src.TotalPage); ``` --- ## 5. Nullable Types ### مشکل Nullable types در C# نیاز به handling خاص دارند. ### Proto با nullable: ```protobuf google.protobuf.Int64Value nullable_id = 1; ``` ### ✅ در DTO: ```csharp public long? NullableId { get; set; } ``` ### ✅ Mapping: ```csharp .Map(dest => dest.NullableId, src => src.NullableId != null ? (long?)src.NullableId.Value : null) ``` --- ## 🎯 Best Practices ### 1. همیشه Explicit Mapping برای Complex Types ```csharp // بهتر است همیشه explicit باشد config.NewConfig() .Map(dest => dest.Prop1, src => src.Prop1) .Map(dest => dest.Prop2, src => src.Prop2); ``` ### 2. استفاده از MapWith برای Custom Logic ```csharp config.NewConfig() .MapWith(src => new Dest { // full control }); ``` ### 3. فایل Profile مجزا برای هر Domain ``` Common/Mappings/ ├── CommissionProfile.cs ├── NetworkProfile.cs ├── ClubProfile.cs └── GeneralMapping.cs // for common types like Unit -> Empty ``` ### 4. تست Mapping ها ```csharp [Fact] public void Should_Map_Request_To_Query() { // Arrange var request = new GetMyWeeklyBalancesRequest { WeekDefinitionId = 7 }; // Act var query = request.Adapt(); // Assert Assert.Equal(7, query.WeekDefinitionId); } ``` --- ## 📁 فایل‌های Profile در پروژه | پروژه | مسیر | محتوا | |-------|------|-------| | CMS | `WebApi/Common/Mappings/` | CommissionProfile, AppVersionProfile | | BackOffice.BFF | `Application/Common/Mappings/` | CommissionProfile | | BackOffice.BFF | `WebApi/Common/Mappings/` | GeneralMapping | | FrontOffice.BFF | `WebApi/Common/Mappings/` | CommissionProfile | --- ## 🔗 منابع - [Mapster Documentation](https://github.com/MapsterMapper/Mapster) - [Protobuf Well-Known Types](https://protobuf.dev/reference/csharp/api-docs/class/google/protobuf/well-known-types/) - [CHANGELOG-2025-12-27.md](../CHANGELOG-2025-12-27.md) - جزئیات بیشتر