c# - AutoMapper 可以为接口(interface)创建映射,然后使用派生类型进行映射吗?

标签 c# automapper

我有一个接口(interface) 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 中不起作用。我知道我可以指定 all BarBaz 但如果有 20 个,我不想管理它们,而是只需按照我上面创建 map 所​​做的操作即可。这可能吗?

最佳答案

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

这很棒,但需要将其注册到映射器注册表中。它需要位于列表的开头,因为我们想要捕获所有 int/IIdentific 源/目标组合(这放置在 Global.asax 等配置中):

var allMappers = MapperRegistry.AllMappers();

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

关于c# - AutoMapper 可以为接口(interface)创建映射,然后使用派生类型进行映射吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4534269/

相关文章:

c# - 映射 IDataReader 时未调用 AutoMapper TypeConverter

asp.net-mvc - Automapper + EF4 + ASP.NET MVC - 出现 'context disposed' 错误(我知道为什么,但如何修复它?)

c# - 什么是最快的通用集合?

c# - 无法连接到任何指定的 MySQL 主机。 <添加名称 ="MySqlSiteMapProvider"

c# - 如何使用 C# 从 Web 客户端浏览本地网络?

c# - 自定义方法 "GetControlsOfType"似乎在上升控制结构以及下降

c# - .Net 4.5+ 中是否仍然存在 C# WCF Proxy ClientBase<T> Disposal 问题

c# - 使用 Entity Framework 保存 AutoMapper 映射的实体集合

asp.net-mvc - DTO 模式 + 延迟加载 + Entity Framework + ASP.Net MVC + 自动映射器

c# - 当查询不为空时,自动映射器投影返回空列表