【问题标题】:Where should I put automapper code?我应该把自动映射器代码放在哪里?
【发布时间】:2014-03-04 09:50:53
【问题描述】:

我在 Asp.net mvc 应用程序中使用 Automapper。 我对 automapper 的使用有疑问

从大量示例代码中,我看到人们直接在操作中使用映射器Mapper.Map<Target>(source),我不确定这是否是一个好的实践,在我看来,我想将Mapper 代码包装在代理对象,而不是让它直接与controller 对话

      public BankflowData CreateBankflowAdjustments(BankflowData addedBankFlow)
      {
         var bankflow = Mapper.Map<Bankflow>(addedBankFlow);
         var newBankflow = Underlying.CreateBankFlowAdjustments(bankflow);
         return Mapper.Map<BankflowData>(newBankflow);
      }

在这个例子中,控制器对 Bankflow 类一无所知,它只知道 dto BankflowData

我想知道这对于使用 AutoMapper 的应用程序是否是一个好习惯?

【问题讨论】:

    标签: c# automapper


    【解决方案1】:

    上一个问题,我回答了ASP.NET MVC with service layer and repository layer, where should the interfaces be defined?

    在我的回答中,我解释说:

    [...] 我有一个这样的典型结构:

    • MyProject.Core
    • MyProject.Domain
    • MyProject.DependencyInjection
    • MyProject.Infrastructure
    • MyProject.Web
    • MyProject.Tests

    基础设施层包含有关日志记录、电子邮件和数据访问的信息。它将包含我选择的ORM。这不是业务逻辑的东西,也不是 UI 的东西。这是我完成工作的解决方案的铁路。它在外层,但它只引用核心。

    在我的例子中,基础设施层还包含 Automapper。核心定义了一个简单的接口(比方说IAutoMapper)和一个存在于基础设施中的简单对象实现它,并且该对象可以通过依赖注入传递给UI层。

    然而 Jimmy Bogard(Automapper 的创造者)在AutoMapper 3.0, Portable Class Libraries and PlatformNotSupportedException

    [...] 如果你抱怨 UI 项目不应该直接引用这个库,因为一些愚蠢的人造建筑师的原因(甚至引用某种臭的圆形蔬菜),我会开车到你家然后打你一巴掌。放下你的傲慢,开始高效工作。

    据我了解,他的意思是可以从 UI 层引用 Automapper。当他说“某种臭的圆形蔬菜”时,他当然指的是Onion Architecture,Jimmy 并不是它的忠实粉丝。

    【讨论】:

    • 感谢您的回答,是的,我同意您将非业务逻辑代码放入具有简单接口的基础设施和包装器 Automapper 中,但我的问题是我是否将域直接暴露给控制器?还是由代理对象包装,并且只将 DTO 暴露给控制器?例如:我有一个服务对象,它返回域对象Cashflow,这是一个相当大的对象,这意味着虽然我有一个 DTO 对象 CashflowDTO,它是一个轻量级对象,但服务对象只将域对象作为参数或结果
    • 所以我有两个选择,1. 将 dto 映射到控制器层中的域对象(我不喜欢) 2. 带有代理对象的包装服务器并将 dto 映射到那里,我更喜欢第二种选择,你的想法是什么?
    • 我总是从 UI 中使用 AutoMapper,因为 UI 获得了 ViewModel,然后我从那里将映射值发送到服务层,服务层继续执行业务逻辑等等。我还有一个 InnerCore => ViewModel => Services,我在其中执行一些隐含 ViewModel 的操作,仅在将结果发送到服务层之前。事情进展顺利。
    【解决方案2】:

    如果您的应用程序中有服务层,最好将自动映射器放在服务层中。无论如何尝试使用扩展方法通过自动映射器映射您的对象,如下所示:

    public static class Mapping
    {
    public static BankflowData CreateBankflowAdjustments(this BankflowData addedBankFlow)
          {
             var bankflow = Mapper.Map<Bankflow>(addedBankFlow);
             var newBankflow = Underlying.CreateBankFlowAdjustments(bankflow);
             return Mapper.Map<BankflowData>(newBankflow);
          }
    }
    

    它将使您的代码更具可读性,并将您的关注点分开。以this了解更多信息

    【讨论】:

    • 这个例子看起来不错,所以你的想法是使用extend方法封装Mapper.Map并调用DTO.ToDomain(),是吗?你也同意映射器代码应该放在服务层而不是控制器层,对吧?
    • 是的,但是如果您有服务层,最好将它们放在那里,因为将 DTO 或 ViewModel 映射到域实体的最佳位置是服务层。虽然如果您的应用程序不够大,您可以将它们放在您的控制器中,但尝试使用扩展方法使您的代码干净。
    猜你喜欢
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多