This came up mapping from models to mvvmcross viewmodels, where you have some container classes you might use, for example:
namespace MvvmCross.Binding
{
interface INC<T>
{
T Value { get; set; }
}
}
class model
{
String name { get; set; }
DateTime when { get; set; }
othermodel data { get; set; }
}
class viewmodel
{
INC<String> Name { get; set; }
INC<String> When { get; set; }
INC<otherviewmodel> Data { get; set; }
}
I need to teach AutoMapper to map from
A
toINC<B>
(and back), without specifiying A or B.Null destination
INC<>
should be created, non-null should not be re-created.Mapping should continue such that
destination.Value = Mapper.Map<A,B>(source)
.Mapping
null --> INC<T>
should result inINC<T>.Value = SomeDefaultValue
By using
ForAllMaps
, you can get the source/destination types and provide a closed, fully generic converter type. This doesn't help if you want to directly call -Map<X,IContainer<Y>
, but you shouldn't need to.With the simple converters:
And I used a helper method here:
This patch allows
typeof(void)
to be used inCreateMap
to express a single parameter that is not contained within a type (i.e. it will match any type) and construct theITypeConverter
as such.The alternative for an unpatched AutoMapper is to substitute
X
andY
withobject
in the below converters. I have added comments to the lines where this would fail. Even ignoring these failings, such an attempt would require reflection and therefore be more complex and less performant.Thanks for Lucians help in the comments.
These mappers will work for
Mapper.Map<INC<String>>("test")
, but not forMapper.Map<String, INC<String>>(null, new NC<String>("I shouldnt be here"))
, since AutoMapper won't send a null source value.This uses a slightly extended ObjectMapper:
Thanks for Lucians help in the comments. This mapper using expressions works, and will receive null values to map as required with a bit of help from this patch and
IObjectMapperInfo.CanMapNullSource = true
.The AM team spent a lot of effort avoiding passing expressions that evaluate to null to Mappers, and it definitely simplifies the AutoMapper.Mappers namespace, so this patch is obviously controversial. I thought about less intrusive ways to signal this like a
NullSafeExpression
, or an anonymous interface moniker likeinterface ICanHandleNullSourceExpressions {}
to try to stem the flow, but I didn't find anything that looks better yet.