Simple Automapper Example

C# AutoMapper - Inhertaince mapping - simple example

You can use this:

 Mapper.Initialize(cfg => cfg.CreateMap<B, A>());
var a_obj = Mapper.Map<A>(b_obj);

Tip : You have to use automapper v6.*

Automapper - mapping simple list to complex nested type

The best answer here would be to not use AutoMapper, since in this case it will just introduce unnecessary complexity instead of simplifying your code. The usage guidelines even state:

DO NOT use AutoMapper except in cases where the destination type is a
flattened subset of properties of the source type


However...

If your project requires using AutoMapper here, one way would be to define a Custom Type Converter that essentially does the same LINQ projection that you would have done otherwise:

public class CarPartConverter : ITypeConverter<IEnumerable<Cars>, IEnumerable<CarsDTO>>
{
public IEnumerable<CarsDTO> Convert(IEnumerable<Cars> source, IEnumerable<CarsDTO> destination, ResolutionContext context)
{
return source
.GroupBy(c => new {c.CarCode, c.CarId})
.Select(g => new CarsDTO
{
CarCode = g.Key.CarCode,
CarId = g.Key.CarId,
CarParts = g.Select(v => new PartsDTO
{
Id = v.PartId,
PartCode = v.PartCode,
Enabled = v.Enabled
}).ToList()
});
}
}

Here's a complete example using that converter:

static void Main(string[] args)
{
IMapper mapper = new MapperConfiguration(cfg => {
cfg.CreateMap<IEnumerable<Cars>, IEnumerable<CarsDTO>>().ConvertUsing<CarPartConverter>();
}).CreateMapper();

List<Cars> cars = new List<Cars>
{
new Cars {PartId = 1, PartCode = "WINDOW", CarId = 1, CarCode = "MUSTANG", Enabled = true},
new Cars {PartId = 2, PartCode = "WHEELS", CarId = 1, CarCode = "MUSTANG", Enabled = true},
new Cars {PartId = 3, PartCode = "BUMPER", CarId = 2, CarCode = "MONDEO", Enabled = true}
};

IEnumerable<CarsDTO> dtos = mapper.Map<IEnumerable<CarsDTO>>(cars);

Console.WriteLine(JsonConvert.SerializeObject(dtos, Formatting.Indented));
Console.ReadLine();
}

Which gives the following results:

Sample Image

How to map a simple poco into a complex object hierachy using automapper?

[For clarity, I'm going to call your Person POCO PersonDTO, since the 3rd party code also has a class called Person.]

There are a couple of ways of doing this. One, which I've used in the past, involves setting up a mapping from PersonDTO to Names, another from PersonDTO to Address, and another from PersonDTO to Reasons. Finally, you add a mapping from PersonDTO to Person. It looks like this (I've left out Reasons, but you get the idea):

var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<PersonDTO, Names>()
.ForMember(d => d.Fullname, o => o.MapFrom(s => s.FullName));
cfg.CreateMap<PersonDTO, Address>()
.ForMember(d => d.AddressLine,
o => o.MapFrom(s => new[] { s.AddressLine1, s.AddressLine2 }));
cfg.CreateMap<PersonDTO, Person>()
.ForMember(d => d.Names, o => o.MapFrom(s => s))
.ForMember(d => d.Address, o => o.MapFrom(s => s));
});
var mapper = config.CreateMapper();

var myPerson = new PersonDTO() {
FirstName = "Bob",
LastName = "Gold",
AddressLine1 = "123 Main Street",
AddressLine2 = "Apt. 2"
};

var theirPerson = mapper.Map<Person>(myPerson);

But a recent version of AutoMapper added a ForPath() method which makes all of this simpler by letting you access inner objects. Now the code collapses to this:

var config = new MapperConfiguration(cfg => 
cfg.CreateMap<PersonDTO, Person>()
.ForPath(d => d.Names.Fullname, o => o.MapFrom(s => s.FullName))
.ForPath(d => d.Address.AddressLine,
o => o.MapFrom(s => new[] { s.AddressLine1, s.AddressLine2 }))
);
var mapper = config.CreateMapper();

Edit: I left out one aspect which may change the balance between these two methods. In the first method, with multiple maps defined, you get for free any fields with matching names. For example, you don't need to explicitly map PesronDTO.City to Address.City (and if you change the case on PersonDTO.FullName to be PersonDTO.Fullname, you'd get that for free as well). But in the second method, you have to explicitly map all nested fields, even if the names match. In your case, I think the first method would probably work better for you, because you'd have to map only 3 fields explicitly and would get the other 4 for free. For the second method, you'd have to do a ForPath() for all 7 fields.

How to set up Automapper in ASP.NET Core

I figured it out! Here's the details:

  1. Add the main AutoMapper Package to your solution via NuGet.

  2. Add the AutoMapper Dependency Injection Package to your solution via NuGet.

  3. Create a new class for a mapping profile. (I made a class in the main solution directory called MappingProfile.cs and add the following code.) I'll use a User and UserDto object as an example.

     public class MappingProfile : Profile {
    public MappingProfile() {
    // Add as many of these lines as you need to map your objects
    CreateMap<User, UserDto>();
    CreateMap<UserDto, User>();
    }
    }
  4. Then add the AutoMapperConfiguration in the Startup.cs as shown below:

     public void ConfigureServices(IServiceCollection services) {
    // .... Ignore code before this

    // Auto Mapper Configurations
    var mapperConfig = new MapperConfiguration(mc =>
    {
    mc.AddProfile(new MappingProfile());
    });

    IMapper mapper = mapperConfig.CreateMapper();
    services.AddSingleton(mapper);

    services.AddMvc();

    }
  5. To invoke the mapped object in code, do something like the following:

     public class UserController : Controller {

    // Create a field to store the mapper object
    private readonly IMapper _mapper;

    // Assign the object in the constructor for dependency injection
    public UserController(IMapper mapper) {
    _mapper = mapper;
    }

    public async Task<IActionResult> Edit(string id) {

    // Instantiate source object
    // (Get it from the database or whatever your code calls for)
    var user = await _context.Users
    .SingleOrDefaultAsync(u => u.Id == id);

    // Instantiate the mapped data transfer object
    // using the mapper you stored in the private field.
    // The type of the source object is the first type argument
    // and the type of the destination is the second.
    // Pass the source object you just instantiated above
    // as the argument to the _mapper.Map<>() method.
    var model = _mapper.Map<UserDto>(user);

    // .... Do whatever you want after that!
    }
    }

Automapper - Create a simple mapping between two classes AND use custom converters for specific types

You use ConvertUsing() to specify the converter you want to use for mapping one type to another. See the examples from Custom Type Converters:

var configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<string, int>().ConvertUsing(s => Convert.ToInt32(s));
cfg.CreateMap<string, DateTime>().ConvertUsing(new DateTimeTypeConverter());
cfg.CreateMap<string, Type>().ConvertUsing<TypeTypeConverter>();
cfg.CreateMap<Source, Destination>();
});

In your case you can register the converter as follow:

var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Source, Destination>();
cfg.CreateMap<string, int?>().ConvertUsing<NullableIntTypeConverter>();
cfg.CreateMap<string, DateTime>().ConvertUsing<DateTimeTypeConverter>();
});

How to use AutoMapper 9 with static implementation without DI?

You can simply build a mapper from the mapper configuration. An example is provided in the AutoMapper docs, which I have reproduced here:

// use cfg to configure AutoMapper
var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>());

var mapper = config.CreateMapper();
// or
var mapper = new Mapper(config);
OrderDto dto = mapper.Map<OrderDto>(order);

Then you could simply set a static field/property somewhere in your project to hold mapper.



Related Topics



Leave a reply



Submit