Reputation: 551
I'm having difficulty ignoring a property on an class which inherits from a base class.
Mapper.CreateMap<FormViewModelBase, EntityBase>()
.Include<FormViewModel, Entity>()
.ForMember(x => x.Id, o => o.Ignore());
Mapper.CreateMap<FormViewModel, Entity>();
The only thing to note here is that the property on the base class is String and the property on the derived class is a Int32.
No matter what, when i try map an instance of FormViewModel to Entity the String based Id property on the Entity class is always set to the Int value from the FormViewModel, even though i have specified to ignore it.
The reason I am using different types for the Id on FormViewModel and Entity, is that I am using RavenDB in a web app and objects can be loaded via a string or an int Id. On the client-side Int Id's are preferred as the standard Raven string based ID's do not play well when generating links.
Can anyone tell me what the problem is here ?
Upvotes: 1
Views: 5806
Reputation: 30628
After raising this as an issue with AutoMapper, the reason that Ignore is not added using Include is because there is no way to un-ignore - mappings can still be overridden in the base class.
The only way that you can currently achieve this behaviour is to decorate the destination property with the [IgnoreMap]
attribute, but this will likely be inconsistent with the rest of your configuration, so you'd need to decide whether it's worth it!
Upvotes: 0
Reputation: 2037
I know this question is a year old but I haven't found a solution in SO that answers this kind of questions. I had identical issue and after some digging the only thing I found is that this behavior is not very well documented. And mapping base classes works but ignoring them doesn't for some reason.
I used this extension method and it worked out for me
public static IMappingExpression<TSource, TDestination>
InheritMappingFromBaseType<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof(TSource);
var desctinationType = typeof(TDestination);
var sourceParentType = sourceType.BaseType;
var destinationParentType = desctinationType.BaseType;
expression
.ForAllMembers(x => x.Condition(r => NotAlreadyMapped(sourceParentType, destinationParentType, r)));
return expression;
}
private static bool NotAlreadyMapped(Type sourceType, Type desitnationType, ResolutionContext r)
{
return !r.IsSourceValueNull &&
Mapper.FindTypeMapFor(sourceType, desitnationType).GetPropertyMaps().Where(
m => m.DestinationProperty.Name.Equals(r.MemberName)).Select(y => !y.IsMapped()).All(b => b);
}
And this is how it's used (Notice that you will need to but the ignore declaration in the base classes mapping)
CreateMap<DerivedClassSource, DerivedClassDestination>()
.InheritMappingFromBaseType()
What it does is mapping any properties that were not mapped using the base class mapping. In other words it breaks the default mapping priorities.
I found the source code here and modified it a bit because some of the original method's code is now implemented in AutoMapper 2 and 3.
Upvotes: 0
Reputation: 6074
You'll need to specify mapping details (like ignoring certain properties) in the mapping of child classes, not parents. For example:
Mapper.CreateMap<ParentA, ParentB>
.Include<ChildA, ChildB>();
Mapper.CreateMap<ChildA, ChildB>
.ForMember(dest => dest.SomeProperty, opt => opt.Ignore());
The reason your code is not working is that you're specifying Ignore() on the parent mappings.
Upvotes: 0
Reputation: 31416
So your base class looks something like this?
public class FormViewModelBase
{
public string Id { get; set; }
// other stuff
}
and your derived class looks like this?
public class FormViewModel : FormViewModelBase
{
public new int Id { get; set; }
// other stuff
}
I'm assuming that's the case.
And if that's the case, then the derived Id is hiding the base Id property.
Anyway, so are you passing around actual instances of a FormViewModel
and making Entity
objects from them?
I see this line:
Mapper.CreateMap<FormViewModel, Entity>();
Which says to me "make me a new Entity
object from the FormViewModel
object I send you and do the default, conventional thing to accomplish this."
So when you call something like:
var anEntity = AutoMapper.Mapper.Map<FormViewModel, Entity>(aFormViewModel);
It's going to use that Map, not the one for the base object. Because it is a derived FormViewModel
.
If you did something like:
Mapper.CreateMap<FormViewModel, Entity>()
.ForMember(x => x.Id, o => o.Ignore());
to handle the mapping of your derived object, it would map it, I suspect, as you would want but it might be helpful to understand a bit more about what you're trying to do.
Upvotes: 1