数据转换过程
前面已经解释了DTO的作用但实现领域对象与DTO之间的转换是一件复杂的事件因此可以建立一个数据转换器实现此功能。在平常的工作里不太多会把“订单管理系统”做成SOA的模式因为在分布式系统中数据的格式与定义大多数由部门之间协定其中包含明确的规则。但由于条件的局限在这里还是想以订单管理为例子希望可以带给你一定的帮助。例子如下在购物车结账页面会包含用户基本信息当前订单信息订单明细信息等多个部分。要完成数据转换首先可以根据页面建立DTO对象在分布式系统中通常会把DTO对象放在一个独立的命名空间里在这个实例里面称之为Business.TransferObject。DTO对象更多时候是面向表现层的需求而建立这里由于表现层页面所需要的只是单个用户单张订单的数据所以在OrderDTO对象里会包含了用户信息和订单资料也存在订单详细列ListOrderItemDTO。当然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 ListOrderItemDTO(); 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.EntityKeynew 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.EntityKeynew System.Data.EntityKey(BusinessContext.Order,ID,orderDTO.OrderID); order.Count orderDTO.Count; if (orderDTO.Delivery.Year!0001orderDTO.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 IListOrderItemDTO _orderItemDTOList; [DataMember] public int PersonID { get{return this._personID;} set{this._personIDvalue;} } .......... .......... } }通过数据转换器可以顺利实现领域模型与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] IListOrderDTO 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] IListOrderDTO 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; } .............. .............. } }