通用映射器而不是拥有大量单独的映射器

发布于 2024-12-06 11:52:11 字数 1096 浏览 1 评论 0原文

我使用 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);
     }
}

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

I am using ASP.NET MVC 3 with Razor and Autofac for dependency injection.

I am thinking of creating a generic mapper. Currently I am using AutoMapper for the mapping between my domain and view model. It can be any mapping framework, but I am using AutoMapper .

Here is my IMapper interface:

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

I then have an IBankMapper interface that implements this IMapper interface. The reason why I did it like this is because I can have many different mappers. Using dependency injection I can know what instance I can inject. So for IBankMapper I will inject BankMapper, ICategoryMapper I will inject CategoryMapper.

IBankMapper interface:

public interface IBankMapper : IMapper
{
}

BankMapper class:

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);
     }
}

As the program grows so will the mapper classes. Is there a way that I can create a generic mapper, one that can be used in the whole application? Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半窗疏影 2024-12-13 11:52:11

您根本不需要创建任何映射器类。

您需要做的就是确保在应用程序开始时调用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();
}

There is absolutely no need for you to create any mapper classes at all.

All you need to do is be sure that you call Mapper.CreateMap at the beginning of your application. You can then use Mapper.Map to do your mapping.

Typically, I create a static class with a single method to handle the creation of my Maps. It looks something like:

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.
    }
}

I then call that method inside Global.asax do ensure that it runs when necessary. In any other spot in my application, I'm free to call Mapper.Map for any of the configured mappings:

protected void Application_Start()
{
    Transformers.Register();
}
往日 2024-12-13 11:52:11

看起来您正在创建这些接口以便能够在单元测试中模拟 AutoMapper。您只需使用 AutoMapper 中的 IMappingEngine 即可实现此目的。

您的类将依赖于将被注入的IMappingEngineIMappingEngine 具有与静态类 Mapper 相同的方法来映射您的对象。

在您的组合根中,您将配置映射器并向 DI 容器注册映射引擎。

像这样的东西:

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

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

It looks like you are creating these interfaces to be able to mock AutoMapper in your unit tests. You can simply use IMappingEngine from AutoMapper for this purpose.

Your classes would have a dependency on IMappingEngine which would be injected. IMappingEngine has the same methods as the static class Mapper to map your objects.

In your composition root you would configure the mapper and register the mapping engine with the DI container.

Something like this:

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

// your classes:
class YourClass
{
    public YourClass(IMappingEngine mappingEngine)
    {
    }
}
笑咖 2024-12-13 11:52:11

正如 Daniel 所说,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);
    }
}

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

As Daniel said, Automapper is already a generic mapper. If you're worried about the direct dependency to automapper in your code, you can hide it behind a little facade, e.g.:

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);
    }
}

This can also help you to model the mapper as an injectable dependency

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文