2011-09-27 44 views
2

我使用ASP.NET MVC 3RazorAutofac为依赖注入。通用映射器,而不是有大量的个人映射器

我正在考虑创建一个通用映射器。目前我正在使用AutoMapper作为我的域和视图模型之间的映射。它可以是任何映射框架,但我使用的是AutoMapper。

这里是我的IMapper接口:

public interface IMapper 
{ 
    object Map(object source, Type sourceType, Type destinationType); 
} 

然后我有一个实现这个IMapper接口的IBankMapper接口。我之所以这样做是因为我可以有许多不同的映射器。使用依赖注入我可以知道我可以注入哪个实例。所以对于IBankMapper我会注入BankMapper,ICategoryMapper我会注入CategoryMapper。

IBankMapper接口:

public interface IBankMapper : IMapper 
{ 
} 

BankMapper类:

public class BankMapper : IBankMapper 
{ 
    static BankMapper() 
    { 
      Mapper.CreateMap<Bank, EditBankViewModel>(); 
      Mapper.CreateMap<EditBankViewModel, Bank>(); 
    } 

    public object Map(object source, Type sourceType, Type destinationType) 
    { 
      return Mapper.Map(source, sourceType, destinationType); 
    } 
} 

随着程序的增长因此将映射器类。有没有一种方法可以创建一个通用映射器,一个可以在整个应用程序中使用的映射器?这可能吗?

+1

我不明白你的问题。 AutoMapper *是一个通用的映射器... –

+0

我想教我的映射器类。我有BankMapper,AccountTypeMapper,ProductMapper,ApplicationMapper等。我想尝试创建1个接受源类和目的类的映射类(如果可能的话)。像TSource和TDestination一样。 –

回答

5

完全不需要您创建任何映射器类。

您只需确保在申请开始时致电Mapper.CreateMap即可。然后你可以使用Mapper.Map来做你的映射。

通常,我使用单一方法创建一个静态类来处理我的地图的创建。它看起来像这样:

public static class Transformers 
{ 
    public static void Register() 
    { 
     Mapper.CreateMap<Bank, EditBankViewModel>(); 
     Mapper.CreateMap<EditBankViewModel, Bank>(); 

     Mapper.CreateMap<Account, EditAccountViewModel>(); 
     Mapper.CreateMap<EditAccountViewModel, Account>(); 

     // And so on. You can break them up into private methods 
     // if you have too many. 
    } 
} 

然后我在Global.asax中调用该方法确保它在必要时运行。在我的应用程序的任何其他地方,我可以自由地调用Mapper.Map任何配置的映射:

protected void Application_Start() 
{ 
    Transformers.Register(); 
} 
+0

您能否为我提供一个将视图模型映射到域模型的单元测试以及如何在您的控制器中实现这一点? –

1

正如丹尼尔说,Automapper已经是一个通用的映射。如果你担心的直接依赖于你的代码automapper,你可以将其隐藏一个小门面后面,如:

public interface IMapper 
{ 
    TDestination Map<TSource, TDestination>(TSource source); 
} 
public class MyMapper :IMapper 
{ 
    public TDestination Map<TSource, TDestination>(TSource source) 
    { 
     AutoMapper.Mapper.CreateMap<TSource, TDestination>(); 
     return AutoMapper.Mapper.Map<TSource, TDestination>(source); 
    } 
} 

这也可以帮助你的映射模型作为注射依赖

+0

不需要这样做。 AutoMapper已经提供了这样一个接口! –

+1

@DanielHilgarth我不知道,谢谢你的评论。也就是说,有些人不想依赖“外部定义的”接口,这种解决方案仍然可以用于这些情况。 – jeroenh

+0

我同意:如果对具体自动映射器的接口的依赖性是一个问题,那么您的Facade接口将有所帮助,并且是一条可行的路。但是,它看起来不像是OPs问题。 –

4

看起来您正在创建这些接口,以便能够在单元测试中模拟AutoMapper。为此,您可以简单地使用AutoMapper的IMappingEngine

你的课程将依赖IMappingEngine这将被注入。 IMappingEngine与静态类Mapper具有相同的方法来映射您的对象。

在您的作文根中,您可以配置映射器并将映射引擎注册到DI容器。

事情是这样的:

// composition root: 
Mapper.CreateMap<Bank, EditBankViewModel>(); 
Mapper.CreateMap<EditBankViewModel, Bank>(); 
builder.Register(Mapper.Engine); 

// your classes: 
class YourClass 
{ 
    public YourClass(IMappingEngine mappingEngine) 
    { 
    } 
} 
+0

好东西.... – jeroenh