6.0 KiB
6.0 KiB
🔧 Mapster - مشکلات رایج و راهحلها
آخرین بروزرسانی: ۷ دی ۱۴۰۴
نسخه Mapster: 7.4.0
📋 فهرست مشکلات
- Protobuf Int64Value Mapping
- MediatR Unit to Empty
- Repeated Fields (List) Mapping
- Property Name Mismatch
- Nullable Types
1. Protobuf Int64Value Mapping
مشکل
فیلدهای google.protobuf.Int64Value (یا StringValue, BoolValue و غیره) که wrapper types هستند، در mapping مستقیم کار نمیکنند.
نشانهها
- مقدار همیشه
0یاnullمیشود - Value در client ست شده ولی در server نادرست دریافت میشود
Proto:
import "google/protobuf/wrappers.proto";
message GetMyWeeklyBalancesRequest {
google.protobuf.Int64Value week_definition_id = 3;
}
❌ کد اشتباه:
config.NewConfig<GetMyWeeklyBalancesRequest, GetMyWeeklyBalancesQuery>()
.Map(dest => dest.WeekDefinitionId, src => src.WeekDefinitionId); // WRONG!
✅ کد صحیح:
config.NewConfig<GetMyWeeklyBalancesRequest, GetMyWeeklyBalancesQuery>()
.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 کار نمیکند
❌ کد اشتباه:
// No mapping defined - will fail at runtime
return await _mediator.Send(command).Adapt<Empty>();
✅ راهحل:
// در GeneralMapping.cs یا هر Profile
config.NewConfig<MediatR.Unit, Google.Protobuf.WellKnownTypes.Empty>()
.MapWith(_ => new Google.Protobuf.WellKnownTypes.Empty());
محل فایل:
BackOffice.BFF.WebApi/Common/Mappings/GeneralMapping.cs
3. Repeated Fields (List) Mapping
مشکل
فیلدهای repeated در protobuf به property RepeatedField<T> تبدیل میشوند که add-only هستند.
نشانهها
- لیست همیشه خالی
- Exception:
Cannot set RepeatedField
Proto:
message GetAllAppVersionsResponse {
repeated AppVersionItem items = 1;
}
❌ کد اشتباه:
config.NewConfig<List<AppVersionItemDto>, GetAllAppVersionsResponse>()
.Map(dest => dest.Items, src => src); // WRONG - Items is read-only
✅ کد صحیح:
config.NewConfig<List<AppVersionItemDto>, GetAllAppVersionsResponse>()
.MapWith(src => CreateResponse(src));
private static GetAllAppVersionsResponse CreateResponse(List<AppVersionItemDto> items)
{
var response = new GetAllAppVersionsResponse();
foreach (var item in items)
{
response.Items.Add(item.Adapt<AppVersionItem>());
}
return response;
}
4. Property Name Mismatch
مشکل
نام property در DTO با نام در proto message یکی نیست.
نشانهها
- فیلد همیشه
nullیا default value - Auto-mapping کار نمیکند
مثال:
message MetaData {
int32 total_page = 2; // -> TotalPage in C#
}
public class MetaDataDto
{
public int TotalPages { get; set; } // WRONG: should be TotalPage
}
✅ راهحل 1 - اصلاح نام:
public class MetaDataDto
{
public int TotalPage { get; set; } // Match proto
}
✅ راهحل 2 - Explicit mapping:
config.NewConfig<MetaData, MetaDataDto>()
.Map(dest => dest.TotalPages, src => src.TotalPage);
5. Nullable Types
مشکل
Nullable types در C# نیاز به handling خاص دارند.
Proto با nullable:
google.protobuf.Int64Value nullable_id = 1;
✅ در DTO:
public long? NullableId { get; set; }
✅ Mapping:
.Map(dest => dest.NullableId,
src => src.NullableId != null ? (long?)src.NullableId.Value : null)
🎯 Best Practices
1. همیشه Explicit Mapping برای Complex Types
// بهتر است همیشه explicit باشد
config.NewConfig<SourceType, DestType>()
.Map(dest => dest.Prop1, src => src.Prop1)
.Map(dest => dest.Prop2, src => src.Prop2);
2. استفاده از MapWith برای Custom Logic
config.NewConfig<Source, Dest>()
.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 ها
[Fact]
public void Should_Map_Request_To_Query()
{
// Arrange
var request = new GetMyWeeklyBalancesRequest { WeekDefinitionId = 7 };
// Act
var query = request.Adapt<GetMyWeeklyBalancesQuery>();
// 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 |