通用映射器,而不是有许多单独的映射器

时间:2011-09-27 13:34:29

标签: c# asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-2

我正在使用ASP.NET MVC 3 RazorAutofac进行依赖注入。

我正在考虑创建一个通用映射器。目前我正在使用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);
     }
}

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

3 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分: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)
    {
    }
}

答案 2 :(得分: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);
    }
}

这也可以帮助您将映射器建模为可注入依赖项