For the given code:
map.ForAllMembers(source =>
{
source.Condition((src, dest, srcVal, destVal) =>
{
if (srcVal == null)
return !(destVal == null);
return !srcVal.Equals(destVal);
});
});
"srcVal" and "destVal" are always the default value for their respective property. I am therefore unable to do conditional mappings using this "ForAllMembers" context as i have no concrete way of being able to retrieve and compare what my Source and Destination values are.
Note: I have walked through this including when it is for the "Colour" property. Both srcVal and destVal are the default for that type (it is a struct, so all internal values are default 0)
For the source property value, there was a bug that I fixed, but the destination property value seemed ok to me. So if you still have issues after the PR is merged, report back with details.
Legendary. Thanks!
I came across this issue and created a test case for it.
This fails with 5.1.1:
using System;
using Should;
using Xunit;
namespace AutoMapper.UnitTests.Bug
{
public class AllMembersNotNullBug
{
public class Rule
{
public string ApplicationName { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string CurrencyCode { get; set; }
public int GroupId { get; set; }
}
[Fact]
public void Should_map_all_null_values_to_its_substitute()
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Rule, Rule>()
.ForAllMembers(opt => opt.Condition((src, dest, srcVal, destVal, c) =>
{
return srcVal != null;
}));
});
var source = new Rule
{
ApplicationName = "Chain42ApplicationName",
CreatedBy = null,
CreatedDate = new DateTime(),
CurrencyCode = null,
GroupId = 42
};
var destination = new Rule
{
ApplicationName = "CommonApplicationName",
CreatedBy = null,
CreatedDate = new DateTime(),
CurrencyCode = "CommonCurrencyCode",
GroupId = 1
};
config.CreateMapper().Map(source, destination);
destination.GroupId.ShouldEqual(42); // OK
destination.ApplicationName.ShouldEqual("Chain42ApplicationName"); // ERROR
}
}
}
To get around it I used a custom resolver.
Hi @vascofernandes can you provide the custom resolver you used, by chance? I am definitely running into this problem as well and have spent a good portion of the day trying to figure out WTF is going on. :stuck_out_tongue: Any assistance/guidance you can provide this newb would be greatly appreciated!
Reverting to 5.0.2.0 also seems to fix this problem, too. :+1: _whew_
For my very particular case I was able to solve it like so, because only one specific property of my mapping was causing me a problem:
public class SystemRuleNotNullProfile : Profile
{
public SystemRuleNotNullProfile()
{
CreateMap<SystemRule, SystemRule>()
.ForMember(t => t.ApplicationName, opt => opt.ResolveUsing<ApplicationNameResolver>())
.ForAllOtherMembers(opt => opt.Condition((src, dest, srcVal, destVal, c) =>
{
return srcVal != null;
}))
//.ForAllMembers(opt => opt.Condition((src, dest, srcVal, destVal, c) => {
// return srcVal != null;
//}))
;
}
}
public class ApplicationNameResolver : IValueResolver<SystemRule, SystemRule, string>
{
public string Resolve(SystemRule source, SystemRule destination, string destMember, ResolutionContext context)
{
if (source.ApplicationName != null)
{
return source.ApplicationName;
}
return destination.ApplicationName;
}
}
Another possibility could be to try something like this for all the properties that matter to you.
CreateMap<A, B>()
.ForMember(t => t.Prop1, opt => opt.Condition((src, dest, srcVal, destVal, c) =>
{
return src.Prop1 != null;
}))
Awesome, thanks for your help, @vascofernandes. 5.0.2.0 reversion has fixed me for now, but this is definitely good to know/see from a knowledge transfer/feature-set perspective.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.