Automapper Mapping Objects of Same Type - Overwrite Bools
If you're implementing some logic on mapping, better do it on each member explicitly.
But if you really want to do it via AutoMapper magic, you can add this condition:
options.Condition((source, destination, member) => (member as bool?) != false);
Automapper - Multi object source and one destination
Map
has an overload that takes a source and destination object:
d = AutoMapper.Mapper.Map<sourceone, destination>(sourceone);
/* Pass the created destination to the second map call: */
AutoMapper.Mapper.Map<sourcetwo, destination>(sourcetwo, d);
Automapper one source to multiple destination
AutoMapper can map from as many sources to as many destinations as you would like, assuming you configure the mapping. For example, your requested scenario:
var configuration = new MapperConfiguration(cfg =>
// Mapping Config
cfg.CreateMap<Source1, Dest2>()
.ForMember(dest => dest.prop5, opt => opt.Ignore())
.ForMember(dest => dest.prop6, opt => opt.Ignore());
cfg.CreateMap<Source1, Dest1>()
.ForMember(dest => dest.Dest2, opt => opt.MapFrom(src => src));
// Reverse Mapping Config
cfg.CreateMap<Dest1, Source1>()
.ForMember(dest => dest.prop4,
opt => opt.MapFrom(src => (src?.Dest2 != null) // ?. w/c#6
? src.Dest2.prop4 // map if can
: null)); // otherwise null
);
// Check AutoMapper configuration
configuration.AssertConfigurationIsValid();
Properties with the same name will map automatically. Any destination properties that don’t have a corresponding source property will need to be ignored.
Once your AutoMapper is configured, you can map as needed with the use of the IMapper interface.
public class Foo {
private IMapper _mapper;
public Foo(IMapper mapper) {
_mapper = mapper;
}
// Map Source1 -> Dest1
public Dest1 Bar(Source1 source) {
return _mapper.Map<Dest1>(source);
}
// Map Dest1 -> Source1
public Source1 Baz(Dest1 dest) {
return _mapper.Map<Source1>(dest);
}
}
Do we need to use asp.net Auto Mapper if the source and destination types are the same
You are using source = destination;
, that will copy reference of the memory location for destination object only. In the example you have provided, it does not really matter since you are adding object to entities.
If you want a complete clone of object at separate memory location to do other processing with the object, use ICloneable and MemberwiseClone, in case, you do not want to use AutoMapper for stuff where mapping is exactly the same.
public class Staff : ICloneable
{
public string FirstName{get;set;}
public string LastName{get;set;}
public int Age{get;set;}
public string Address{get;set;}
public object Clone()
{
return this.MemberwiseClone();
}
}
Then, you can use source = (Staff)destination.Clone();
This will allow shallow copy only. If you want deep copy, you can serialize and deserialize.
How to map some source properties to a wrapped destination type using AutoMapper?
According to this issue on AutoMapper GitHub page, there is no direct way to do it.
But there is some workarounds. For example - reflection.
In this case you need to know wrapper type and implement converter for desired types. In this example it's MapAndWrapConverter
from TSource
to Wrap<TDestination>
CreateWrapMap
method creates two bindings:SourceAddress -> Wrap<DestinationAddress>
and SourceContact -> Wrap<DestinationContact>
which allow you to map SourceContant
to wrapped DestinationContact
.
internal class Program
{
public static void Main()
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<SourceAddress, DestinationAddress>();
cfg.CreateMap<SourceContact, DestinationContact>();
cfg.CreateWrapMap(
//func selecting types to wrap
type => typeof(DestinationModelBase).IsAssignableFrom(type)
&& !type.IsAbstract,
typeof(Wrap<>),
typeof(MapAndWrapConverter<,>));
});
var mapper = config.CreateMapper();
//Using AutoFixture to create complex object
var fixture = new Fixture();
var srcObj = fixture.Create<SourceContact>();
var dstObj = mapper.Map<Wrap<DestinationContact>>(srcObj);
}
}
public static class AutoMapperEx
{
public static IMapperConfigurationExpression CreateWrapMap(
this IMapperConfigurationExpression cfg,
Func<Type, bool> needWrap, Type wrapperGenericType,
Type converterGenericType)
{
var mapperConfiguration =
new MapperConfiguration((MapperConfigurationExpression)cfg);
var types = Assembly.GetExecutingAssembly().GetTypes();
foreach (var dstType in types.Where(needWrap))
{
var srcType = mapperConfiguration.GetAllTypeMaps()
.Single(map => map.DestinationType == dstType).SourceType;
var wrapperDstType = wrapperGenericType.MakeGenericType(dstType);
var converterType = converterGenericType.MakeGenericType(srcType, dstType);
cfg.CreateMap(srcType, wrapperDstType)
.ConvertUsing(converterType);
}
return cfg;
}
}
public class MapAndWrapConverter<TSource, TDestination>
: ITypeConverter<TSource, Wrap<TDestination>>
{
public Wrap<TDestination> Convert(
TSource source, Wrap<TDestination> destination, ResolutionContext context)
{
return new Wrap<TDestination>
{
Payload = context.Mapper.Map<TDestination>(source)
};
}
}
CreateWrapMap
method is a little bit messy, especially the part with finding matching types. But it can be refined according to your needs.
Related Topics
How to Redirect to Login Page If Session Is Not Available in MVC
Moq - Non-Overridable Members May Not Be Used in Setup/Verification Expressions
Why Am I Getting Error Cs0246: the Type or Namespace Name Could Not Be Found
How to Remove Illegal Characters from Path and Filenames
How to Disable Cursor in Textbox
Windows Service Cannot Access Network Location (Unc) Path
Error 5:Access Denied When Starting Windows Service
Unit Test a Method That Returns a Void
Clearing a Textbox Leaves an Invisible Character
How to Download a File from a Url in C#
How to Loop Through All Fields in an Object in C#
How to Trim All Elements in a List
How to Refresh an Entity Framework Core Dbcontext
Get Properties and Values from Unknown Object
How to Pass Parameter from @Url.Action to Controller Function
How to Check If a Datetime Value Is Empty or Not in a Put Request