Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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
titleNote

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:


Code Block
languagec#
yield return CodeListMap.Create<AbsenceCauseTypeIdentifierEnum, AbsenceCauseTypeIdentifierType>();



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
languagec#
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
languagec#
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
languagec#
// Uden extensionmetode
.ForMember(dest => dest.Identifier, opt => opt.MapFrom(src => src.Id))

// Med extensionmetode
.ForMemberMapFrom(dest => dest.Identifier, src => src.Id)


IgnoreMember

Code Block
languagec#
// Uden extensionmetode
.ForMember(dest => dest.Identifier, opt => opt.Ignore())

// Med extensionmetode
.IgnoreMember(dest => dest.Identifier)


ForMemberUseValue

Code Block
languagec#
// 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
languagec#
[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

...