我应该把automapper代码放在哪里?

5

我正在使用Asp.net mvc应用程序中的Automapper。 关于Automapper的用法,我有一个问题。

在很多示例代码中,我看到人们直接在操作中使用映射器 Mapper.Map<Target>(source) ,我不确定这是否是一个好的实践方法。从我的角度来看,我希望将Mapper代码包装在代理对象中,而不是直接让它与控制器通信。

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

在这个例子中,控制器对于类Bankflow一无所知,它所知道的只有数据传输对象BankflowData
我想知道,在使用自动映射器的应用程序中,这是否是一个好的实践?
2个回答

6

在之前的问题中,我回答了 ASP.NET MVC与服务层和存储库层,接口应该定义在哪里?

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

[...] 我有一个典型的结构,如下:

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

Infrastructure 层包含有关日志记录、电子邮件和数据访问的信息。它将包含我选择的 ORM。它不是业务逻辑内容,也不是 UI 内容。它是解决方案的铁路,用于完成任务。它位于外层,但仅引用 Core。

在我的情况下,基础架构层还包含Automapper。核心定义了一个简单的接口(比如说IAutoMapper),基础架构中存在的一个简单对象实现了它,这个对象可以通过依赖注入传递到UI层。
然而,Automapper的创建者Jimmy Bogard在AutoMapper 3.0, Portable Class Libraries and PlatformNotSupportedException中说:
[...]如果你因为一些愚蠢的假架构原因(甚至参考某种臭气熏天的圆形蔬菜)而抱怨UI项目不应该直接引用这个库,我会开车到你家并打你一顿。下马威并开始变得高效起来吧。
据我所知,他的意思是从UI层引用Automapper是可以的。当他说“某种臭气熏天的圆形蔬菜”时,他当然是指洋葱架构,而Jimmy并不是它的忠实拥护者。

谢谢你的回答,是的,我同意你将非业务逻辑代码放在基础设施和包装器Automapper中,并使用一个简单的接口。但我的问题是,我应该直接将领域对象暴露给控制器吗?还是通过代理对象进行封装,只将DTO暴露给控制器?例如:我有一个服务对象,返回一个名为Cashflow的领域对象,它是一个相当大的对象,同时我还有一个轻量级的DTO对象CashflowDTO。服务对象只接受领域对象作为参数或结果。 - Sean
所以我有两个选择,1. 在控制器层将DTO映射到领域对象(我不喜欢这个选项)2. 使用代理对象包装服务器并在那里映射DTO,我更喜欢第二个选择,你有什么想法? - Sean
我总是从UI中使用AutoMapper,因为UI有ViewModel,然后我将映射值发送到Service层,继续业务逻辑等操作。我还有一个InnerCore => ViewModel => Services的过程,在这个过程中,我在发送结果到Service层之前进行了一些仅涉及ViewModel的操作。事情进展得非常顺利。 - David Létourneau

3
如果您的应用程序有服务层,最好将自动映射器放在服务层中。无论如何,尝试使用扩展方法通过自动映射器来映射您的对象,方法如下:
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);
      }
}

使用它可以使您的代码更易读,并且可以分离关注点。点击这里了解更多信息。


这个例子看起来不错,那你的想法是使用extend方法来封装Mapper.Map并调用DTO.ToDomain(),对吗?你也同意将映射器代码放置在服务层而不是控制器层,对吗? - Sean
是的,但如果您有服务层,则最好将它们放在那里,因为将DTO或ViewModel映射到领域实体的最佳位置是服务层。尽管如果您的应用程序不太复杂,也可以将它们放在控制器中,但请尝试使用扩展方法使您的代码更加清晰。 - Ehsan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接