AutoMapper可以为界面创建地图,然后使用派生类型进行映射吗?

时间:2010-12-26 15:07:37

标签: c# automapper

我有一个接口IFoo:

public interface IFoo
{
    int Id { get; set; }
}

然后是一个具体的实现:

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; }
}

我希望能够映射所有 IFoo,但要指定其派生类型:

Mapper.CreateMap<int, IFoo>().AfterMap((id, foo) => foo.Id = id);

然后映射(没有明确地为Bar和Baz创建地图):

var bar = Mapper.Map<int, Bar>(123);
// bar.Id == 123

var baz = Mapper.Map<int, Baz>(456);
// baz.Id == 456

但这在1.1中不起作用。我知道我可以指定所有 BarBaz但是如果有20个这样的话,我不想管理它们而只是拥有我上面所做的用于创建地图。这可能吗?

1 个答案:

答案 0 :(得分:2)

我找到了解决这个问题的方法。我创建了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;
        }
    }
}

这很棒,但需要注册到mapper注册表。它需要位于列表的开头,因为我们想要捕获所有int/IIdentifiable源/目标组合(这被放置在诸如Global.asax之类的配置中):

var allMappers = MapperRegistry.AllMappers();

MapperRegistry.AllMappers = () => new IObjectMapper[]
{
    new IdentifiableMapper(),
}.Concat(allMappers);