Mapping multiple objects to one object with AutoMapper - c#

I have 6 properties in C Class and I want to map 3 of my properties from A method with output class A and 3 others from B method with output Class B
First, I map A to C (which is defined at MappingProfile class and 3 other properties are ignored) and then I map B to C (which has been defined like previous one)
My problem is that in the second Map my c object is always going to be override with b object and 3 other properties (which I got them from a object) come back as null (because they don't exist in B class).
In the end, I want to Have all data from a and b objects in my c object.
Mapping operations -
Adaptee Amethod = new Adaptee();
List<A> a = Amethod.A().ToList();
List<B> b = Amethod.B().ToList();
List<C> c1 = _mapper.Map<List<A>, List<C>>(a);
List<C> c = _mapper.Map(b, c1);
Mapping profiles -
public MappingProfile()
{
CreateMap<A, C>()
.ForMember(z => z.FN, opt => opt.MapFrom(x => x.FN))
.ForMember(z => z.LN, opt => opt.MapFrom(x => x.LN))
.ForMember(z => z.uniqe, opt => opt.MapFrom(x => x.uniqe))
.ForMember(z => z.Addr, opt => opt.Ignore())
.ForMember(z => z.HomeTown, opt => opt.Ignore())
.ForMember(z => z.NID, opt => opt.Ignore());
CreateMap<B, C>()
.ForMember(z => z.Addr, opt => opt.MapFrom(x => x.Addr))
.ForMember(z => z.HomeTown, opt => opt.MapFrom(x => x.HomeTown))
.ForMember(z => z.NID, opt => opt.MapFrom(x => x.NID))
.ForMember(z => z.FN, opt => opt.Ignore())
.ForMember(z => z.LN, opt => opt.Ignore())
.ForMember(z => z.uniqe, opt => opt.Ignore());
}
I'm using AutoMapper.Extensions.Microsoft.DependancyInjection v8.1.0.

you can use this method for multipli Object
services.AddSingleton(provider => new MapperConfiguration(cfg =>
{
cfg.AddProfile(new sampleProfileMapper());
}).CreateMapper());

Related

How to merge two nested object into one using AutoMapper

Hi I have been using AutoMapper to convert my objects, and now I'm trying to merge two nested objects into one, but I can't figure out how to do it.
I have the following code:
These are my source objects
class SourceSubItemA
{
string subPropertyA;
}
class SourceSubItemB
{
string subPropertyB;
}
class Source
{
SourceSubItemA subItemA;
SourceSubItemB subItemB;
}
Destination objects
class DestinationSubItem
{
string propertyA;
string propertyB;
}
class Destination
{
DestinationSubItem destItem;
}
This is my Automapper configuration
Mapper.CreateMap<SourceSubItemA, DestinationSubItem>()
.ForMember(dest => propertyA, opt => opt.MapFrom(src => src.subPropertyA));
Mapper.CreateMap<SourceSubItemB, DestinationSubItem>()
.ForMember(dest => propertyB, opt => opt.MapFrom(src => src.subPropertyB));
// Probably I have to do something more here.
Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.destItem, opt => opt.MapFrom(src => src.subItemA));
And finally I'm using the mapper by this way
Mapper.Map<Destination>(sourceObject);
The expected result must be a Destination object with a subitem with both properties filled.
Please Help!
As I can see, Destination is just a wrapper of DestinationSubItem that is the one that really needs to get the values from Source.
In that case, you could define a mapper from Source to Destination that puts in dest.destItem the result of mapping from Source directly to DestinationSubItem.
Here an example:
Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.destItem, opt => opt.MapFrom(src => Mapper.Map<DestinationSubItem>(src));
Mapper.CreateMap<Source, DestinationSubItem>()
.ForMember(dest => dest.propertyA, opt => opt.MapFrom(src => src.subItemA.subPropertyA)
.ForMember(dest => dest.propertyB, opt => opt.MapFrom(src => src.subItemB.subPropertyB);

AutoMapper and IDataReader

I would like to map data from IDateReader to some class but can not do it simply. I wrote the following code:
cfg.CreateMap<IDataReader, MyDto>()
.ForMember(x => x.Id, opt => opt.MapFrom(rdr => rdr["Id"]))
.ForMember(x => x.Name, opt => opt.MapFrom(rdr => rdr["Name"]))
.ForMember(x => x.Text, opt => opt.MapFrom(rdr => rdr["Text"]));
UPD: I tried to use Automapper.Data from Nuget but it depends on
NETStandard.Library but I use .NET Framework 4.5
But this way is bad for me because I have to describe mapping rule for each column. Is it possible to avoid describing all of these rules?
You could use an ITypeConverter, such as the following:
public class DataReaderConverter<TDto> : ITypeConverter<IDataReader, TDto> where TDto : new
{
public TDto Convert(IDataReader source, TDto destination, ResolutionContext context)
{
if (destination == null)
{
destination = new TDto();
}
typeof(TDto).GetProperties()
.ToList()
.ForEach(property => property.SetValue(destination, source[property.Name]));
}
}
cfg.CreateMap<IDataReader, MyDto>().ConvertUsing(new DataReaderConverter<MyDto>());

Automapper 4.2, How to re use the mappings

I have a automapper mapping that work's just fine , I just don't know if I'll have to re-write it everytime I need to map my model to my viewModel vice-versa. I wonder if there is a way where once it is mapped, automapper knows what to do.
I could create static methods with the mappings in one "helper" class, but I don't know if it is the right approach.
Here is the mapping.
var ax =
new MapperConfiguration(cfg =>
{
cfg.CreateMap<Pessoa, PessoaViewModel>()
.ForMember(dest => dest.cod_endereco, opt => opt.MapFrom(src => src.endereco.codigo))
.ForMember(dest => dest.logradouro, opt => opt.MapFrom(src => src.endereco.logradouro))
.ForMember(dest => dest.cod_tipolograd, opt => opt.MapFrom(src => src.endereco.tipo.codigo))
.ForMember(dest => dest.cod_munic_ender, opt => opt.MapFrom(src => src.endereco.municipio.codigo))
.ForMember(dest => dest.nome_munic_ender, opt => opt.MapFrom(src => src.endereco.municipio.nome))
.ForMember(dest => dest.numero, opt => opt.MapFrom(src => src.endereco.numero))
.ForMember(dest => dest.complemento, opt => opt.MapFrom(src => src.endereco.complemento))
.ForMember(dest => dest.cep, opt => opt.MapFrom(src => src.endereco.cep))
.ForMember(dest => dest.bairro, opt => opt.MapFrom(src => src.endereco.bairro))
;
}).CreateMapper().Map<Pessoa, PessoaViewModel>(p);
If I use the mapping like below:
new MapperConfiguration(cfg => cfg.CreateMap<Pessoa, PessoaViewModel>()).CreateMapper().Map<Pessoa, PessoaViewModel>(p);
the fields that I used forMember method to map them, stays null.

AutoMapper: ignore some parameters when calling the Map() function

I want to ignore some mappings while I call the Map function.
Here's where I create my Map:
Mapper.CreateMap<User, UserViewModel>()
.ForMember(dest => dest.WebLicenseCount, opt => opt.MapFrom(src => GetCount(src, "0801")))
.ForMember(dest => dest.MobileLicenseCount, opt => opt.MapFrom(src => GetCount(src, "0901")))
.ForMember(dest => dest.ExcelAddInLicenseCount, opt => opt.MapFrom(src => GetCount(src, "0895")))
.ForMember(dest => dest.NextExpirationDate, opt => opt.MapFrom(src => src.Licences.Min(l => l.LicenceProducts.Min(lp => lp.ExpirationDate))))
.ForMember(dest => dest.Licences, opt => opt.MapFrom(src => src.Licences.ToList()))
.ForMember(dest => dest.TicketsCount, opt => opt.MapFrom(src => src.Tickets.Count(t => t.Status != (int)TicketStatusType.Closed)))
.ForMember(dest => dest.ParentContact, opt => opt.MapFrom(src => src.Contact))
.ForMember(dest => dest.ParentUser, opt => opt.MapFrom(src => src.User2))
.ForMember(dest => dest.Contacts, opt => opt.MapFrom(src => src.Contacts))
.ForMember(dest => dest.MainContact, opt => opt.Ignore())
.ForMember(dest => dest.SessionID, opt => opt.Ignore())
;
In my controller I do this:
users = Mapper.Map<UserViewModel[]>(response.users);
I want to ignore in this call, the mapping for those proprieties :WebLicenseCount, MobileLicenseCount, ExcelAddInLicenseCount.
There's anyway to do this?
If this is something you want to do only once then overwrite the mentioned properties in users with the corresponding response.users after the Map() function. If this is something you would want to do often then it means you either need to change your mapping or create a second type (e.g. SpecialUser) for those situations and define different set of mappings for this type.

AutoMapper 2.1.267.0 does not map simple int? property

I have the following classes
Source:
public class NewBusinessSubmission
{
//other properties
public int? TermTypeId { get; set; }
}
Destination:
NewBusinessSubmission class inherits from the PolicyTransaction class shown below (yes it is VB.NET):
<System.Serializable()> Public MustInherit Class PolicyTransaction
Inherits Framework2.BusinessBase(Of PolicyTransaction)
Implements IDisposable
...........
Public Property TermTypeId() As Nullable(Of Integer)
Get
CanReadProperty(True)
If Not _PolicyTermsDataRow.IsTermTypeIdNull Then
Return Me._PolicyTermsDataRow.TermTypeId
End If
End Get
Set(ByVal value As Nullable(Of Integer))
If Nullable(Of Integer).Equals(value, Me.TermTypeId) Then Exit Property
CanWriteProperty(True)
If value.HasValue Then
Me._PolicyTermsDataRow.TermTypeId = value.Value
Else
Me._PolicyTermsDataRow.SetTermTypeIdNull()
End If
AfterTermTypeIdChanged()
Me.PropertyHasChanged()
End Set
End Property
...........
End Class
Mapping Configuration below does not set the TermTypeId:
Mapper.CreateMap<NewBusinessSubmission, NewBusiness>()
.ForMember(x => x.PolicyTxnNum, opt => opt.Ignore())
.ForMember(x => x.ContactProducerLicId, opt => opt.Ignore())
.ForMember(x => x.PolicyNames, opt => opt.Ignore())
.ForMember(x => x.PolicyExp, opt => opt.Ignore());
This one does not work either:
Mapper.CreateMap<NewBusinessSubmission, NewBusiness>()
.ForMember(x => x.PolicyTxnNum, opt => opt.Ignore())
.ForMember(x => x.ContactProducerLicId, opt => opt.Ignore())
.ForMember(x => x.PolicyNames, opt => opt.Ignore())
.ForMember(x => x.PolicyExp, opt => opt.Ignore())
.ForMember(x => x.TermTypeId, opt => opt.MapFrom(x => x.TermTypeId));
I call Map like this:
var newBusiness = Mapper.Map<NewBusinessSubmission, NewBusiness>(newBusinessSubmission);
All the other properties that have similar code in the Set() method map correctly and I can also manually map TermTypeId like this:
newBusinessInstance.TermTypeId = newBusinessSubmissionInstance.TermTypeId;
Any ideas as to why this property is not mapped correctly?
Thanks.

Categories

Resources