数据转换过程

前面已经解释了DTO的作用,但实现领域对象与DTO之间的转换是一件复杂的事件,因此可以建立一个数据转换器实现此功能。

在平常的工作里,不太多会把"订单管理系统"做成SOA的模式,因为在分布式系统中,数据的格式与定义大多数由部门之间协定,其中包含明确的规则。但由于条件的局限,在这里还是想以订单管理为例子,希望可以带给你一定的帮助。例子如下:在购物车结账,页面会包含用户基本信息,当前订单信息,订单明细信息等多个部分。

要完成数据转换,首先可以根据页面建立DTO对象,在分布式系统中,通常会把DTO对象放在一个独立的命名空间里,在这个实例里面称之为Business.TransferObject。DTO对象更多时候是面向表现层的需求而建立,这里由于表现层页面所需要的只是单个用户,单张订单的数据,所以在OrderDTO对象里会包含了用户信息和订单资料,也存在订单详细列List<OrderItemDTO>。当然,DTO的设计可以随着需求而修改。

在SOA系统里,DTO是远程服务数据的载体,所以会把DTO附上可序列化特性,这此例子中会使用WCF的数据契约实现OrderDTO和OrderItemDTO。

如图,要实现数据转换,就应该建立数据转换器。在这里OperationAssembler就是一个数据转换器,它是数据转换的核心,它是领域对象与DTO之间实现转换的工具。要在多个对象之间实现数据转换实在是一件非常麻烦的事,所以我一直提倡注意DTO对象的兼容性,使单个DTO对象可以适用于多个外观层,以减少数据转换所带来的麻烦。

复制代码
namespace Business.Service.ApplicationService
{
    public class OperationAssembler
    {
        //把领域对象转换成DTO
        public static OrderDTO GetOrderDTO(Order order,Person person)
        {
            OrderDTO orderDTO = new OrderDTO();
            if (person != null)
            {
                orderDTO.EMail = person.EMail.GetString();
                orderDTO.Address = person.Address.GetString();
                orderDTO.Name = person.Name.GetString();
                orderDTO.PersonID = person.ID;
                orderDTO.Point = person.Point.GetInt();
                orderDTO.Telephone = person.Telephone.GetString();
            }
            if (order != null)
            {
                orderDTO.PersonID = order.PersonID;
                orderDTO.Count = order.Count.GetInt();
                orderDTO.Delivery = order.Delivery.GetDateTime();
                orderDTO.Favorable = order.Favorable.GetDouble();
                orderDTO.Freightage = order.Freightage.GetDouble();
                orderDTO.OrderID = order.ID;
                orderDTO.OrderNumber = order.OrderNumber.GetString();
                orderDTO.Price = order.Price.GetDouble();
                orderDTO.TotalPrice = order.TotalPrice.GetDouble();
                var orderItemList = order.OrderItem.ToList();
                if (orderItemList.Count != 0)
                {
                    var orderItemDTO = new List<OrderItemDTO>();
                    foreach (var orderItem in orderItemList)
                        orderItemDTO.Add(GetOrderItemDTO(orderItem));
                    orderDTO.OrderItemList = orderItemDTO;
                }
            }
            return orderDTO;
        }

        public static OrderItemDTO GetOrderItemDTO(OrderItem orderItem)
        {
            OrderItemDTO orderItemDTO = new OrderItemDTO();
            orderItemDTO.Count = orderItem.Count.GetInt();
            orderItemDTO.Goods = orderItem.Goods.GetString();
            orderItemDTO.OrderID = orderItem.OrderID;
            orderItemDTO.OrderItemID = orderItem.ID;
            orderItemDTO.Price = orderItem.Price.GetDouble();
            return orderItemDTO;
        }

        //把DTO转换成多个对象
        public static void SetOrder(OrderDTO orderDTO, out Person person, out Order order)
        {
            person = new Person();
            person.EntityKey=new System.Data.EntityKey("BusinessContext.Person","ID",orderDTO.PersonID);
            person.Address = orderDTO.Address;
            person.EMail = orderDTO.EMail;
            person.ID = orderDTO.PersonID;
            person.Name = orderDTO.Name;
            person.Point = orderDTO.Point;
            person.Telephone = orderDTO.Telephone;

            order = new Order();
            order.EntityKey=new System.Data.EntityKey("BusinessContext.Order","ID",orderDTO.OrderID);
            order.Count = orderDTO.Count;
            if (orderDTO.Delivery.Year!=0001&&orderDTO.Delivery.Year!=9999)
                order.Delivery = orderDTO.Delivery;
            order.Favorable = orderDTO.Favorable;
            order.Freightage = orderDTO.Freightage;
            order.ID = orderDTO.OrderID;
            order.OrderNumber = orderDTO.OrderNumber;
            order.PersonID = orderDTO.PersonID;
            order.Price = orderDTO.Price;
            order.TotalPrice = orderDTO.TotalPrice;
            var orderItemDTOList = orderDTO.OrderItemList;
            if (orderItemDTOList.Count() != 0)
                foreach (var orderItemDTO in orderItemDTOList)
                    order.OrderItem.Add(GetOrderItem(orderItemDTO));
        }

        public static OrderItem GetOrderItem(OrderItemDTO orderItemDTO)
        {
            OrderItem orderItem = new OrderItem();
            orderItem.EntityKey = new System.Data.EntityKey("BusinessContext.OrderItem", "ID", orderItemDTO.OrderItemID);
            orderItem.Count = orderItemDTO.Count;
            orderItem.Goods = orderItemDTO.Goods;
            orderItem.ID = orderItemDTO.OrderItemID;
            orderItem.OrderID = orderItemDTO.OrderID;
            orderItem.Price = orderItemDTO.Price;
            return orderItem;
        }
    }
}

//数据传输对象 DTO
namespace Business.TransferObject
{
    [DataContract]
    public class OrderItemDTO
    {
        private int _orderItemID;
        private int _orderID;
        private string _goods;
        private double _price;
        private int _count;

        [DataMember]
        public int OrderItemID
        {
            get { return _orderItemID; }
            set { _orderItemID = value; }
        }
        ............
        ............
    }

    [DataContract]
    public class OrderDTO
    {
        private int _personID;
        private string _name;
        private string _address;
        private string _telephone;
        private int _point;
        private string _email;
        private int _orderID;
        private string _orderNumber;
        private int _count;
        private double _freightage;
        private double _favorable;
        private DateTime _delivery;
        private double _price;
        private double _totalPrice;
        private IList<OrderItemDTO> _orderItemDTOList;

        [DataMember]
        public int PersonID
        {
            get{return this._personID;}
            set{this._personID=value;}
        }
        ..........
        ..........
    }
}

通过数据转换器,可以顺利实现领域模型与DTO之间的转换,协调应用层服务的运行。

4. 应用层的发布

在开发SOA系统的时候,应用层的服务需要使用远程方法对外开放,在接收到请求的时候,它可以调用领域层服务获取运算结果,然后通过数据转换器OperationAssembler把运算结果转换成DTO,最后返还到表现层。在起初,我曾尝试对应每个应用层的对象建立一个远程接口,但经过多次重构以后,我觉得行程对象就是一个简单的对外接口,对象之间不存在什么逻辑关系。所以更简单的方法是使用外观模式,建立少数的几个远程服务类,把所有的应用层对象的方法都包含在内。

可以留意代码,OperationService包括了对Person模型和Order模型的所有操作。而且每个操作都只是简单地调用应用层服务 (ApplicationService) 获得计算结果,然后使用数据转换器 (OperationAssembler)转换数据,当中并不存在任何的业务逻辑。

复制代码
namespace Business.Service.ApplicationService
{
    [ServiceContract]
    public interface IOperationService
    {
        [OperationContract]
        int AddOrder(ref OrderDTO orderDTO);

        [OperationContract]
        int DeleteOrder(OrderDTO orderDTO);

        [OperationContract]
        int UpdateOrder(ref OrderDTO orderDTO);

        [OperationContract]
        IList<OrderDTO> GetOrderByPerson(int personID);

        [OperationContract]
        OrderDTO GetOrder(int orderID);

        [OperationContract]
        int AddPerson(ref OrderDTO orderDTO);

        [OperationContract]
        int UpdatePerson(ref OrderDTO orderDTO);

        [OperationContract]
        OrderDTO GetPerson(int personID);

        [OperationContract]
        IList<OrderDTO> GetPersonList();

        [OperationContract]
        OrderDTO Payment(int orderID);
    }

    public class OperationService:IOperationService
    {
        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public int AddOrder(ref OrderDTO orderDTO)
        {
            OrderService orderService = new OrderService();
            Order order = GetOrder(orderDTO);
            int n = orderService.AddOrder(order);
            orderDTO = OperationAssembler.GetOrderDTO(order, null);
            return n;
        }

        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public int DeleteOrder(OrderDTO orderDTO)
        {
            OrderService orderService = new OrderService();
            return orderService.DeleteOrder(GetOrder(orderDTO));
        }

        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public int UpdateOrder(ref OrderDTO orderDTO)
        {
            OrderService orderService = new OrderService();
            Order order = GetOrder(orderDTO);
            int n = orderService.UpdateOrder(order);
            orderDTO = OperationAssembler.GetOrderDTO(order, null);
            return n;
        }
        ..............
        ..............
    }
}
相关推荐
Scott9999HH13 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔13 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社14 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海14 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖15 小时前
JDK 26 新特性详解
java·开发语言
马优晨15 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区17 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大18 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai18 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说18 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json