How to Specify Mapping Rule When Names of Properties Differ

How to specify mapping rule when names of properties differ

Never mind, I myself found a solution:

Mapper.CreateMap<Employee, EmployeeDto>()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.Name));

Usage of Automapper when property names are different

You can try recognizing postfixes:

Mapper.Initialize(cfg => {
cfg.RecognizePostfixes("Field");
cfg.CreateMap<Source, Dest>();
});

Recognizing prefixes also works local to profiles, if it's just a set of maps that this applies to.

Automapper: mapping between different types

For mapping both ways this configuration works for me:

var mapperConfiguration = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Entity, EntityDto>()
.ForMember(dest => dest.EntityChildrenIds, opt => opt.MapFrom(src => src.Children))
.ReverseMap();

cfg.CreateMap<EntityChild, int>().ConvertUsing(child => child.Id);
cfg.CreateMap<int, EntityChild>().ConvertUsing(id => new EntityChild
{
Id = id
});
});

Since the properties have different names we need to configure that mapping.

Then just add general mappings from EntityChild to int and back again and we're done.

AutoMapper Mapping one property to two properties by condition

I have found solution. The solution is pretty simple and clear. It turns out as follow:

Full code:

public class Program
{

class A
{
public string ProductionDivision { get; set; }
}

class B
{
private object _productionDivision;

public enum ProductionDivisionOneofCase
{
None = 0,
IsNullproductionDivision = 15,
ProductionDivisionValue = 16,
}
private ProductionDivisionOneofCase _productionDivisionCase = ProductionDivisionOneofCase.None;

public bool IsNullProductionDivision
{
get { return _productionDivisionCase == ProductionDivisionOneofCase.IsNullproductionDivision ? (bool)_productionDivision : false; }
set
{
_productionDivision = value;
_productionDivisionCase = ProductionDivisionOneofCase.IsNullproductionDivision;
}
}

public string ProductionDivisionValue
{
get { return _productionDivisionCase == ProductionDivisionOneofCase.ProductionDivisionValue ? (string)_productionDivision : ""; }
set
{
_productionDivision = value;
_productionDivisionCase = ProductionDivisionOneofCase.ProductionDivisionValue;
}
}
}

public class StrinToBoolCustomResolver
: IValueConverter<string, bool>
{
public bool Convert(string sourceMember, ResolutionContext context)
{
return sourceMember == null;
}
}

public class MyAutoMapperProfile
: Profile
{
public MyAutoMapperProfile()
{
// add post and pre prefixes to add corresponding properties in the inner property map
RecognizeDestinationPostfixes("Value");
RecognizeDestinationPrefixes("IsNull");

// add mapping for "value" property
this.ForAllPropertyMaps(map => map.SourceMember.Name + "Value" == map.DestinationName,
(map, expression) =>
{
expression.Condition((source, dest, sMem, destMem) =>
{
return sMem != null;
});
expression.MapFrom(map.SourceMember.Name);
});

// add mapping for "IsNull" property
this.ForAllPropertyMaps(map => "IsNull" + map.SourceMember.Name == map.DestinationName,
(map, expression) =>
{
expression.Condition((source, dest, sMem, destMem) =>
{
return (bool)sMem;
});
//expression.MapFrom(map.SourceMember.Name);
expression.ConvertUsing<string, bool>(new StrinToBoolCustomResolver(), map.SourceMember.Name);
});

CreateMap<A, B>();
//.ForMember(g => g.IsNullProductionDivision, m =>
//{
// m.PreCondition(s => s.ProductionDivision == null);
// m.MapFrom(b => true);
//});
//.ForMember(g => g.ProductionDivisionValue, m =>
//{
// m.PreCondition(s => s.ProductionDivision != null);
// m.MapFrom(b => b.ProductionDivision);
//});
}
}

public static void Main(string[] args)
{
var configuration = new MapperConfiguration(cfg => {
cfg.AddProfile(new MyAutoMapperProfile());
});

var mapper = new Mapper(configuration);
mapper.ConfigurationProvider.AssertConfigurationIsValid();
var a = new A()
{
ProductionDivision = null
};
// b._productionDivisionCase will be equal IsNullproductionDivision
var b = mapper.Map<B>(a);

var c = new A()
{
ProductionDivision = "dsd"
};
// d._productionDivisionCase will be equal ProductionDivisionValue
var d = mapper.Map<B>(c);
}
}

Clarification:

  1. add (post/pre)fixes to add corresponding properties to inner property map. It need to do here because our properties should be catched by AutoMapper. Otherwise properties will be abandoned and mapper configuration will be failed.

  2. After that, we configurate how these properties need to be mapping. We call ForAllPropertyMaps method, filtering all properties and setting a rule to mapping properties suitable with our filter. When the mapper object is creating, the execution plan will be built taking look the specified filters.

  • For "Value" property we add a condition to check whether the source property is not null. If it is null, then mapping will be missed.
  • For "IsNull" property First of all, we add a converter to convert string type to bool type. The converter just compares the source string property with null value. If the source property equals null, then the converter returns true. So, the condition receives a true value, returns true, and mapping will be done. Otherwise the converter returns false, so the condition returns false and mapping will be missed.

Thus, the mapping of source property will occur to different destination properties depending on whether the source property is null value. Besides that, corresponding set methods of corresponding destination properties will be not called if it not must to be called.

Auto mapper makes error when mapping class with another class properties

The namespace for Data class is different, even though their content is the same.

Delete these

Sample Image

and refer to source Data class namespace or

If you don't want to delete them, add the following configuration

public class CASADetailsProfile: Profile
{
public CASADetailsProfile()
{
// Source -> Target
CreateMap<CASADetialsRequest, CASADetails>();
CreateMap<CASADetails, CASADetialsResponse>();


CreateMap<Sources.Data, Destinations.Data>();
CreateMap<Sources.Account, Destinations.Account>();
CreateMap<Sources.Transaction, Destinations.Transaction>();
CreateMap<Sources.LinkedCard, Destinations.LinkedCard>();
CreateMap<Sources.JointParty, Destinations.JointParty>();
}
}

Change Sources namespace and Destinations namespace to the namespace that you have

How do I get AutoMapper to map classes whose type isn't known at compile time?

Looking at the docs, it seems you can tell AutoMapper about the inheritance like so:

var config = new MapperConfiguration(cfg =>
{
//Other mapping

cfg.CreateMap<v1.Event, v2.Event>() //or even <object, v2.Event>
.Include<v1.Conference, v2.Conference>()
.Include<v1.ReligiousCeremony, v2.ReligiousCeremony>();

cfg.CreateMap<v1.Conference, v2.Conference>();
cfg.CreateMap<v1.ReligiousCeremony, v2.ReligiousCeremony>();
});


Related Topics



Leave a reply



Submit