美文网首页DDD领域驱动设计
DDD领域驱动设计——应用层,AutoMapper

DDD领域驱动设计——应用层,AutoMapper

作者: SkylerSkr | 来源:发表于2020-03-22 00:16 被阅读0次

    前言

    源码地址:
    https://github.com/SkylerSkr/Skr3D

    好了,我们有了只关心自己的领域层,辛苦持久化的基础设施层。那么又有人问了,领域对象不能直接扔给UI层,要处理一下才能扔给UI层。这里你没有EF了,看你怎么操作。
    那么,AutoMapper就走来了!
    PS:应用层是很薄的一层,不写任何业务代码,只负责推送请求和返回响应值。

    视图模型(Dtos)

    我们先来写视图模型,就是扔给UI层的实体

        public class OrderViewModel
        {
            [Key]
            public Guid Id { get; set; }
    
            [Required(ErrorMessage = "The Order Name is Required")]
            [MinLength(2)]
            [MaxLength(100)]
            [DisplayName("Name")]
            public string Name { get; set; }
    
            public List<OrderItemViewModel> Items { get; set; }
    
            public string Province { get; set; }
    
            public string City { get; set; }
    
            public string County { get; set; }
    
            public string Street { get; set; }
        }
    
    
        public class OrderItemViewModel
        {
    
            [Required(ErrorMessage = "The Item Name is Required")]
            [MinLength(2)]
            [MaxLength(100)]
            [DisplayName("Name")]
            public string Name { get; set; }
        }
    
        /// <summary>
        /// 地址
        /// </summary>
        public class AddressViewModel
        {
            /// <summary>
            /// 省份
            /// </summary>
            [Required(ErrorMessage = "The Province is Required")]
            [DisplayName("Province")]
            public string Province { get; set; }
    
            /// <summary>
            /// 城市
            /// </summary>
            public string City { get; set; }
    
            /// <summary>
            /// 区县
            /// </summary>
            public string County { get; set; }
    
            /// <summary>
            /// 街道
            /// </summary>
            public string Street { get; set; }
        }
    

    AutoMapper

    然后我们用AutoMapper来做VIewModel和Domain(领域实体)的映射

        /// <summary>
        /// 静态全局 AutoMapper 配置文件
        /// </summary>
        public class AutoMapperConfig
        {
            public static MapperConfiguration RegisterMappings()
            {
                //创建AutoMapperConfiguration, 提供静态方法Configure,一次加载所有层中Profile定义 
                //MapperConfiguration实例可以静态存储在一个静态字段中,也可以存储在一个依赖注入容器中。 一旦创建,不能更改/修改。
                return new MapperConfiguration(cfg =>
                {
                    //这个是领域模型 -> 视图模型的映射,是 读命令
                    cfg.AddProfile(new DomainToViewModelMappingProfile());
                    //这里是视图模型 -> 领域模式的映射,是 写 命令
                    cfg.AddProfile(new ViewModelToDomainMappingProfile());
                });
            }
        }
    
        public class DomainToViewModelMappingProfile : Profile
        {
            /// <summary>
            /// 配置构造函数,用来创建关系映射
            /// </summary>
            public DomainToViewModelMappingProfile()
            {
                CreateMap<Order, OrderViewModel>()
                    .ForPath(d => d.Province, o => o.MapFrom(s => s.Address.Province))
                    .ForPath(d => d.City, o => o.MapFrom(s => s.Address.City))
                    .ForPath(d => d.County, o => o.MapFrom(s => s.Address.County))
                    .ForPath(d => d.Street, o => o.MapFrom(s => s.Address.Street)); ;
    
                CreateMap<OrderItem, OrderItemViewModel>();
    
            }
        }
    
        public class ViewModelToDomainMappingProfile : Profile
        {
            public ViewModelToDomainMappingProfile()
            {
                //手动进行配置
                CreateMap<OrderViewModel, Order>()
                    .ForPath(d => d.Address.Province, o => o.MapFrom(s => s.Province))
                    .ForPath(d => d.Address.City, o => o.MapFrom(s => s.City))
                    .ForPath(d => d.Address.County, o => o.MapFrom(s => s.County))
                    .ForPath(d => d.Address.Street, o => o.MapFrom(s => s.Street))
                    .ForPath(d=>d.OrderItem,o=>o.MapFrom(s=>s.Items));
    
                CreateMap<OrderItemViewModel, OrderItem>();
    
            }
        }
    

    这里有两个配置文件,Domain到ViewModel还有ViewModel到Domain

    领域层实现

    有了领域对象和Dtos的映射,接着就是实现应用层了。

        /// <summary>
        /// 定义 IOrderAppService 服务接口
        /// 并继承IDisposable,显式释放资源
        /// 注意这里我们使用的对象,是视图对象模型
        /// </summary>
        public interface IOrderAppService : IDisposable
        {
            void Register(OrderViewModel OrderViewModel);
            IEnumerable<OrderViewModel> GetAll();
        }
    
        /// <summary>
        /// OrderAppService 服务接口实现类, 继承 服务接口
        /// 通过 DTO 实现视图模型和领域模型的关系处理
        /// 作为调度者,协调领域层和基础层,
        /// 这里只是做一个面向用户用例的服务接口,不包含业务规则或者知识
        /// </summary>
        public class OrderAppService : IOrderAppService
        {
            // 注意这里是要IoC依赖注入的,还没有实现
            private readonly IOrderRepository _OrderRepository;
            // 用来进行DTO
            private readonly IMapper _mapper;
    
            public OrderAppService(
                IOrderRepository OrderRepository,
                IMapper mapper
            )
            {
                _OrderRepository = OrderRepository;
                _mapper = mapper;
            }
    
            public IEnumerable<OrderViewModel> GetAll()
            {
                var orders = _OrderRepository.GetAll();
                var orderList = orders.ToList();
                return _mapper.Map<IEnumerable<OrderViewModel>>(orders);
            }
    
            public OrderViewModel GetById(Guid id)
            {
                return _mapper.Map<OrderViewModel>(_OrderRepository.GetById(id));
            }
    
            public void Register(OrderViewModel OrderViewModel)
            {
                var order = _mapper.Map<Order>(OrderViewModel);
                _OrderRepository.Add(order);
                _OrderRepository.SaveChanges();
            }
    
            public void Dispose()
            {
                GC.SuppressFinalize(this);
            }
        }
    

    第一次跑通项目

    那么我们有了应用层,领域层,基础设施层。就有了最简单的DDD的框架,只需要在StartUp中注入简单的IOC就可以使用。

     public class NativeInjectorBootStrapper
        {
            public static void RegisterServices(IServiceCollection services)
            {
    
                // ASP.NET HttpContext dependency
                services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    
                // 注入 应用层Application
                services.AddScoped<IOrderAppService, OrderAppService>();
    
    
                // 领域层 - Memory
                services.AddSingleton<IMemoryCache>(factory =>
                {
                    var cache = new MemoryCache(new MemoryCacheOptions());
                    return cache;
                });
    
                // 注入 基础设施层 - 数据层
                services.AddScoped<IOrderRepository, OrderRepository>();
                services.AddScoped<OrderContext>();
            }
        }
    

    我把这个最简单的体现DDD思想的例子单独建立一个分支,OnlyDDD。
    接下来我会加入CQRS+Event来实现微服务。

    相关文章

      网友评论

        本文标题:DDD领域驱动设计——应用层,AutoMapper

        本文链接:https://www.haomeiwen.com/subject/ctwuyhtx.html