简体   繁体   中英

How unflattening commands to complex types

I'm not yet dependent to either Mapster or AutoMapper. For now I'm using handwritten mappings because I couldn't find a mapper who could do this with smaller code.

The problem is how do we map flatten structures to complex objects? I think a lot of people could benefit from a good mapping example for such a complex object. I've got even a mapping condition based on CopyOfficeAddressAsInvoiceAddress whether or not the office address needs to be copied as invoice address. I've looked all over the place but couldn't get it to work.

Maybe I should also use a different naming to make it more clear for the mapping algorithm?!

The biggest question could such a map being resolved by a mapper or is this to complex? Al the demo's I've seen were using dto and model objects that are quite similar to each other. I didn't get the point of mapping an object to another object that 99% similar to each other.

I have a Command (I'm using Mediatr) that looks like as follows:

public class Command  : IRequest<IActionResult>
{
            public string AccountName { get; set; }

            public string ContactFirstName { get; set; } 
            public string ContactLastName { get; set; } 
            public string ContactEMail { get; set; } 
            public string ContactPhoneNumber { get; set; } 

            public string BankAccount { get; set; } 
            public string Bank { get; set; } 

            public string OfficeName { get; set; } 

            public string OfficeAddressStreet { get; set; } 
            public int OfficeAddressStreetNumber { get; set; } 
            public string? OfficeAddressStreetNumberAddition { get; set; } 
            public string OfficeAddressPostalcode { get; set; } 
            public string OfficeAddressCity { get; set; } 
            public string OfficeAddressCountry { get; set; } 

            public string? OfficeInvoiceAddressStreet { get; set; }  = null;
            public int? OfficeInvoiceAddressStreetNumber { get; set; }  = null;
            public string? OfficeInvoiceAddressStreetNumberAddition { get; set; }  = null;
            public string? OfficeInvoiceAddressPostalcode { get; set; }  = null;
            public string? OfficeInvoiceAddressCity { get; set; }  = null;
            public string? OfficeInvoiceAddressCountry { get; set; }  = null;

            //[Ignore]
            public bool? CopyOfficeAddressAsInvoiceAddress  { get; set; } = false;
            
            public string? AssociationIdentifier { get; set; } = null;
}

And I want it to be mapped to the following models :

public class Account
    {
        public int Id { get; set; }

        public string AccountName { get; set; }

        public IList<Contact> Users { get; set; }

        public IList<Office> Offices { get; set; }

        public string Bank { get; set; }
        public string BankAccount { get; set; }

        public string? AssociationIdentifier { get; set; }
}
public class Office
    {
        public int Id { get; set; }

        public string Name { get; set; }
        public Address ContactAddress { get; set; }
        public Address InvoiceAddress { get; set; }
        public bool HeadQuarter { get; set; }
    }
public class Address
    {
        public int Id { get; set; }

        public string Street { get; set; }
        public string Postalcode { get; set; }
        public int StreetNumber { get; set; }
        public string StreetNumberAddition { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
    }
public class Contact
    {
        public int Id { get; set; }

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string EMail { get; set; }
        public string PhoneNumber { get; set; }
   }

First of all, my experience is mainly using Automapper, and it is definitely possible to map complex types like this.

But your command does not need to be completely flat. There is nothing inherently wrong with DTOs being similar to your domain models. Using Automapper this is fairly easy as properties with the same name are mapped 1:1.

It could be that you are submitting a form with all the properties flattened in one object. In that case you could define either a seperate map for this object and each domain object.

CreateMap<AccountDto, Account>(); // mapping logic omitted
CreateMap<AccountDto, Office>();
...

Or you could map the one object to a range of objects using Tuples.

CreateMap<AccountDto, (Account, Office, ...)>(); // mapping logic omitted

But if you define seperate DTOs and make mapping profiles for them, it will probably ease your whole mapping experience. For copying the address, you can simply do something like this, in that case.

if (copyAddress) 
{
    office.InvoiceAddress = _mapper.Map<Address>(addressDto);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM