数据转换过程

前面已经解释了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;
        }
        ..............
        ..............
    }
}
相关推荐
2501_947575807 小时前
计算机毕业设计之jsp开山车行二手车交易系统
java·开发语言·hadoop·python·信息可视化·django·课程设计
骑士雄师7 小时前
java面试题 4:鉴权
java·开发语言
时间的拾荒人9 小时前
C语言字符函数与字符串函数完全指南
c语言·开发语言
帅次9 小时前
Android 高级工程师面试:Java 基础知识 近1年高频追问 22 题
android·java·面试
蓝胖的四次元口袋9 小时前
Java集合(4)
java·哈希算法
2501_948106919 小时前
计算机毕业设计之基于jsp教科研信息共享系统
java·开发语言·信息可视化·spark·课程设计
TanYYF9 小时前
spring ai入门教程二
java·人工智能·spring
SeeYa-J9 小时前
Spring IOC(Inversion of Control)
java·spring·rpc
取经蜗牛9 小时前
Python 第一阶段完全指南:从零到第一个实用工具
开发语言·python