Table of Contents |
---|
Introduktion
I DFDG tilstræbes det, at AutoMapper anvendes til mapning mellem klasser. AutoMapper anvendes i dag primært i følgende situationer:
- Mapning mellem servicetyper og domænemodel (ServiceConverter)
- Mapning mellem domænemodel og wsrm-typer (WsrmConverter)
- Mapning mellem domænemodel og eksterne serviceklasser fx ved kald til Jobnet (ExternalServiceMapper)
ServiceConverter
ServiceConvertere aka ServiceMappere anvendes til at konvertere mellem servicetyper og domæneobjekter. For nye services bør følgende principper følges:
Placering og navngivning
For alle services laves en converter klasse, der nedarver fra MapperBase. Converteren navngives efter servicen, fx vil InterviewService have en converter, der hedder InterviewServiceConverter. Det er besluttet, at vi kalder det en converter og ikke en mapper. MapperBase findes under namespacet DFDG.ServiceGateway.Utilities
Kodelister
Når en converter nedarver fra MapperBase, mappes der automatisk mellem kodeliste-enums og kodelistetyper - uanset retning og uanset om de properties, der mappes mellem er nullable eller ej. Eksempel:
...
Info | |||||
---|---|---|---|---|---|
| |||||
For at konvertering mellem enums og kodelistetyper fungerer for nye kodelister, skal der tilføjes en linje i filen KC.AMS.Model.Converters.CodeListMappingInitializer. Eksempel fra eksisterende kodeliste:
|
Konventioner
Undgå explicitte mappings
Undgå at mappe mellem properties med samme navn. AutoMapper gør det for dig. AutoMapper kan selv finde ud af, det, hvis casing er forskellig og propertytyperne for forskellige. Eksempel på, hvad man IKKE skal gøre:
...
Code Block | ||
---|---|---|
| ||
config.CreateMap<Model.InterviewModel, Service.InterviewType>() .ForMemberMapFrom(dest => dest.Identifier, src => src.IdIdentifier) |
Undgå desuden at kalde UseValue, med angivelse af defaultværdier som vist nedenfor. Værdien false er default for en bool, hvormed dette statement er overflødigt:
Code Block | ||
---|---|---|
| ||
config.CreateMap<Model.InterviewModel, Service.InterviewType>()
.ForMemberUseValue(dest => dest.IsSomthing, false) |
Anvend extentionmetoder
For at gøre livet lettere for udviklerne er er udviklet extensionmetoder til de mest gængse mapping-relaterede operationer:
ForMemberMapFrom
Code Block | ||
---|---|---|
| ||
// Uden extensionmetode .ForMember(dest => dest.Identifier, opt => opt.MapFrom(src => src.Id)) // Med extensionmetode .ForMemberMapFrom(dest => dest.Identifier, src => src.Id) |
IgnoreMember
Code Block | ||
---|---|---|
| ||
// Uden extensionmetode .ForMember(dest => dest.Identifier, opt => opt.Ignore()) // Med extensionmetode .IgnoreMember(dest => dest.Identifier) |
ForMemberUseValue
Code Block | ||
---|---|---|
| ||
// Uden extensionmetode .ForMember(dest => dest.Identifier, opt => opt.UseValue(42)) // Med extensionmetode .ForMemberUseValue(dest => dest.Identifier, 42) |
Test
Der findes en unittest - AssertMapperConfigurationsAreValid(), der automatisk kalder AssertConfigurationIsValid på alle convertere, der nedarver fra MapperBase. Dermed er der ikke behov for at skrive selvstændige tests til de enkelte convertere.
...
Code Block | ||
---|---|---|
| ||
[TestMethod] [TestCategory("UnitTest"), TestCategory("MyPlan")] public void MyPlanPdfContainerMapper_ConversionSuccessful() { var mapper = new MyPlanPdfContainerMapper(); MyPlanModel myPlan = _fixture.Create<MyPlanModel>(); List<ActivityItemModel> activityItems = _fixture.Build<ActivityItemModel>().CreateMany().ToList(); KC.AMS.Model.ServiceModel.PersonNameStructureType personName = _fixture.Create<KC.AMS.Model.ServiceModel.PersonNameStructureType>(); var container = new MyPlanContainer(myPlan, activityItems, personName); var pdfContainer = new MyPlanPdfContainer(container, _fixture.Create<bool>(), _fixture.Create<bool>()); var result = mapper.Convert(pdfContainer, _fixture.Create<bool>()); Assert.IsNotNull(result); // We don't check that all properties are converted correctly (because there are many), but just that the converter doesn't throw an exception } |
Self-contained
Det tilstræbes, at convertere laves, så de ikke behøver at kommunikere med andre komponenter eller gå i databasen. En converter bør være self-contained og modtage alle nødvendige data gennem dens offentlige metoder
WsrmConverter
For wsrmconvertere gælder stort set samme regelsæt som for serviceconvertere med den forskel, at der laves én converter per wsrm-besked.
ExternalServiceConverter
For converters brugt til konvertering mellem domænemodel og proxyklasser til en ekstern service, gælder samme regelsæt som for serviceconvertere
...