说说 abp vnext 与 Mapster

环境: abp vnext(4.2) , Mapster(7.5)

一、 使用 Mapster作为默认对象转换

  Abp Vnext 默认使用 AutoMapper(9.0+) 作为对象转换器,比较麻烦的一点是需要不断的配置 AutoMapper的Profile,DTO比较多的话个人觉得还是比较麻烦的,尤其是Web层还有ViewModel到DTO的转换,那么能不能使用Mapster作为默认转换器呢,Mapster不需要注册对象的转换,可以省下不少创建Profile的时间,而且据官方测试效率也比AutoMapper高,答案是可以的,而且很容易。可以参考官方文档:Object To Object Mapping   说明。

  第一步:实现 IObjectMapper

    //[Dependency(lifetime: ServiceLifetime.Transient, TryRegister = true)]
    public class MapsterObjectMapper<TSource, TDestination> : IObjectMapper<TSource, TDestination>//, ITransientDependency
    { 
        public TDestination Map(TSource source)
        { 
            return source.Adapt<TDestination>( );
        }

        public TDestination Map(TSource source, TDestination destination)
        {
            return source.Adapt<TSource, TDestination>(destination);
        }
    }

  注意,我注释了[Dependency] 和ITransientDependency ,因为按官方文档,这两个类需实现其中一个,框架就会自动注册Services,但是我没测试成功。所以下一步就是在Module代码中注册Services。

  第二步: 在需要使用的Module中注册 Services:

    context.Services.AddTransient(typeof(IObjectMapper<,>), typeof(MapsterObjectMapper<,>));

  如此,便注册了泛型的对象转换器。

二、 切换Mapster存在的问题

  那么,官方为什么不直接使用Mapster呢?我觉得大概是会破坏DDD的设计。一般abp vnext 里的Entity 结构如下

 public partial class TestClass: AuditedEntity<Guid>
    {   
        public string Keyword1 { get; set; } 
        public string Keyword2 { get; set; }  
 
        protected TestClass()
        {
        }

        public TestClass(
            Guid id,
            string keyword1,
            string keyword2, 
        ) : base(id)
        {
            Keyword1 = keyword1;
            Keyword2 = keyword2; 
        }

    

 这个对象有一个protectd 的构造函数用于反射实例化,一个多参数的构造函数用于控制使用者创建对象的完整性,AutoMapper是能支持这个结构的。Mapster却不能,

它需要一个公开的无实参构造函数,或者配置有参的构造函数,参考官方文档:  Map to constructor 。对于有参构造函数,由于 Guid id 这个字段,而我的DTO不包含Id 字段,Mapster无法匹配创建Entity,所以也会报错。

   对于Mapster的使用,我感觉有两种方式

   1. 只在 Web项目使用,由ViewModel到DTO的互相转换

   2. Service层也使用,但是Entity的有参构造函数不能有DTO不包含的字段

posted @ 2021-03-09 17:43  富贵东坡  阅读(631)  评论(0编辑  收藏  举报