5

我正在创建一个多层应用程序,将 asp.net mvc 应用程序作为最高层。

架构如下(---> 表示引用):

表示层--->服务层--->业务层---->数据访问层---->数据库

此外,还有一个称为“基础设施”的层,它被所有层引用。

每一层都有自己的实体。例如:在表示层我们可能有 UserViewModel,在服务层 UserDTO,在业务层 UserBDO,最后在数据访问层,User。

automapper 用于自动化不同类型之间的转换。

我读到一些开发人员建议将映射创建放在 Global.asax 中,但很明显,如果您有一个多层应用程序,则无法在其中创建所有映射。您不能在表示层中将 User 与 UserBDO 映射。

所以,我在问最简洁的方法来管理多层应用程序中的映射集中化。您甚至可以建议对架构进行更改。

4

2 回答 2

1

我建议你已经有了答案——如果你不能在一个地方访问所有类型——只需将映射配置分成几个部分。此解决方案在大型项目中更易于维护(想象一下在一个配置中包含 100 或 1000 个映射)。例如,我们使用特定的映射器将第三方 WCF 合同转换为自定义 DTO。此映射器与 WCF 客户端一起位于单独的项目中。因此无法从外部访问合同和映射。

于 2015-09-28T10:03:32.390 回答
0

我尝试回答我自己的问题:如果有任何对您不利的地方,请随时纠正我。

我将使用以下词语:

  • 层:在这种情况下,层是垂直意义上的应用程序模块(从数据库到用户界面)

  • 模块:横向意义上的应用程序的一个区域,例如“CRM”、“产品”、“会计”……每个都有它的代码在不同的层。

如果您的应用程序分为 n 层和 n 个模块,则以下可能是特定模块和层的特定类的示例。

public static class ProductMapper
{
    static ProductMapper()
    {
        MapProductBDOToDTO();
        MapProductDTOToBDO();

        MapProductCategoryBDOToDTO();
        MapProductCategoryDTOToBDO();

        MapIvaBDOToDTO();
        MapIvaDTOToBDO();

        MapProductSupplierBDOToDTO();
        MapProductSupplierDTOToBDO();

        MapProductPictureBDOToDTO();
        MapProductPictureDTOToBDO();

        MapProductNoteBDOToDTO();
        MapProductNoteDTOToBDO();

        MapStockProductBDOToDTO();
        MapStockProductDTOToBDO();

        MapTagBDOToDTO();
        MapTagDTOToBDO();
    }


    public static TTargetType Convert<TToConvert, TTargetType>(TToConvert toConvert)
    {
        return Mapper.Map<TTargetType>(toConvert);
    }


    private static void MapProductDTOToBDO()
    {
        Mapper.CreateMap<ProductDTO, ProductBDO>();
    }

    private static void MapProductBDOToDTO()
    {
        Mapper.CreateMap<ProductDTO, ProductBDO>().ReverseMap();
    }

    private static void MapProductCategoryDTOToBDO()
    {
        Mapper.CreateMap<ProductCategoryDTO, ProductCategoryBDO>();
    }

    private static void MapProductCategoryBDOToDTO()
    {
        Mapper.CreateMap<ProductCategoryBDO, ProductCategoryDTO>();
    }

    private static void MapIvaDTOToBDO()
    {
        Mapper.CreateMap<IvaDTO, IvaBDO>();
    }

    private static void MapIvaBDOToDTO()
    {
        Mapper.CreateMap<IvaBDO, IvaDTO>();
    }

    private static void MapProductSupplierDTOToBDO()
    {
        Mapper.CreateMap<ProductSupplierDTO, ProductSupplierBDO>();
    }

    private static void MapProductSupplierBDOToDTO()
    {
        Mapper.CreateMap<ProductSupplierDTO, ProductSupplierBDO>().ReverseMap();
    }

    private static void MapProductPictureDTOToBDO()
    {
        Mapper.CreateMap<ProductPictureDTO, ProductPictureBDO>();
    }

    private static void MapProductPictureBDOToDTO()
    {
        Mapper.CreateMap<ProductPictureDTO, ProductPictureBDO>().ReverseMap();
    }

    private static void MapProductNoteDTOToBDO()
    {
        Mapper.CreateMap<ProductNoteDTO, ProductNoteBDO>();
    }

    private static void MapProductNoteBDOToDTO()
    {
        Mapper.CreateMap<ProductNoteDTO, ProductNoteBDO>().ReverseMap();
    }

    private static void MapStockProductDTOToBDO()
    {
        Mapper.CreateMap<StockProductDTO, StockProductBDO>();
    }

    private static void MapStockProductBDOToDTO()
    {
        Mapper.CreateMap<StockProductDTO, StockProductBDO>().ReverseMap();
    }

    private static void MapTagDTOToBDO()
    {
        Mapper.CreateMap<TagDTO, TagBDO>();
    }

    private static void MapTagBDOToDTO()
    {
        Mapper.CreateMap<TagDTO, TagBDO>().ReverseMap();
    }

如您所见,它是一个带有静态构造函数的静态类,这意味着在应用程序生命周期内,构造函数的调用次数不会超过一次。第一次调用 Convert 方法时,会调用构造函数并创建所有映射。第二次、第三次、第四次……在同一会话期间,您将调用 Convert 方法的 n 次,将不会调用构造函数。

优点:

  • 不能多次创建特定映射
  • 映射仅在您需要时创建(在这种情况下,当您使用产品时)。您不会在应用程序启动时创建 1000 个映射,然后只使用其中的 5 个或 6 个。

缺点:

  • 开发人员可以使用他/她想要的所有类型调用通用 Convert 方法,不检查类型。顺便说一句,使用泛型方法需要更少的代码,如果尚未创建映射,则 AutoMapper 将抛出异常。
于 2015-09-29T12:14:03.947 回答