I have an interface IFoo:
public interface IFoo
{
int Id { get; set; }
}
And then a concrete implementation:
public class Bar : IFoo
{
public int Id { get; set; }
public string A { get; set; }
}
public class Baz : IFoo
{
public int Id { get; set; }
public string B { get; set; }
}
I'd like to be able to map all IFoo
but specifying their derived type instead:
Mapper.CreateMap<int, IFoo>().AfterMap((id, foo) => foo.Id = id);
And then map (without explicitly creating maps for Bar and Baz):
var bar = Mapper.Map<int, Bar>(123);
// bar.Id == 123
var baz = Mapper.Map<int, Baz>(456);
// baz.Id == 456
But this doesn't work in 1.1. I know I could specify all开发者_如何学编程 Bar
and Baz
but if there are 20 of these, I'd like to not have to manage them and rather just have what I did above for creating the map. Is this possible?
I've found a solution to this problem. I created an implementation of an IObjectMapper
:
// In this code IIdentifiable would be the same as IFoo in the original post.
public class IdentifiableMapper : IObjectMapper
{
public bool IsMatch(ResolutionContext context)
{
var intType = typeof(int);
var identifiableType = typeof(IIdentifiable);
// Either the source is an int and the destination is an identifiable.
// Or the source is an identifiable and the destination is an int.
var result = (identifiableType.IsAssignableFrom(context.DestinationType) && intType == context.SourceType) || (identifiableType.IsAssignableFrom(context.SourceType) && intType == context.DestinationType);
return result;
}
public object Map(ResolutionContext context, IMappingEngineRunner mapper)
{
// If source is int, create an identifiable for the destination.
// Otherwise, get the Id of the identifiable.
if (typeof(int) == context.SourceType)
{
var identifiable = (IIdentifiable)mapper.CreateObject(context);
identifiable.Id = (int)context.SourceValue;
return identifiable;
}
else
{
return ((IIdentifiable)context.SourceValue).Id;
}
}
}
This is great but it needs to be registered to the mapper registry. It needs to go at the beginning of the list since we want to catch all int/IIdentifiable
source/destination combinations (this is placed in configuration such as Global.asax):
var allMappers = MapperRegistry.AllMappers();
MapperRegistry.AllMappers = () => new IObjectMapper[]
{
new IdentifiableMapper(),
}.Concat(allMappers);
精彩评论