数据转换过程
前面已经解释了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; } .............. .............. } }

相关新闻

领域层的服务

领域层的服务

在第二节已基本介绍过服务的作用了,领域层服务的作用主要是为了解决业务上的逻辑问题,更多的时候,服务是一个与业务相关的动作。比如在上述例子中: 在Order表里记录的是每次交易的过程,每次商品的送货费(F…

2026/7/5 4:56:39阅读更多 →
LitCAD:15分钟从零基础到二维CAD绘图高手

LitCAD:15分钟从零基础到二维CAD绘图高手

LitCAD:15分钟从零基础到二维CAD绘图高手 【免费下载链接】LitCAD A very simple CAD developed by C#. 项目地址: https://gitcode.com/gh_mirrors/li/LitCAD 想要掌握专业级的CAD绘图技能,却担心软件复杂、学习曲线陡峭?LitCAD正是为…

2026/7/5 4:51:39阅读更多 →
LangGraph快速入门与底层原理剖析

LangGraph快速入门与底层原理剖析

LangGraph 以图的方式构建语言代理 官方文档地址:https://langchain-ai.github.io/langgraph/ LangGraph 是一个用于构建具有 LLMs 的有状态、多角色应用程序的库,用于创建代理和多代理工作流。与其他 LLM 框架相比,它提供了以下核心优势&…

2026/7/5 4:51:39阅读更多 →
JPEXS Free Flash Decompiler:深入SWF逆向工程与资源提取实战指南

JPEXS Free Flash Decompiler:深入SWF逆向工程与资源提取实战指南

JPEXS Free Flash Decompiler:深入SWF逆向工程与资源提取实战指南 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler 作为一名技术开发者或安全研究人员,当你面对遗…

2026/7/5 6:06:43阅读更多 →
ParsecVDisplay:Windows虚拟显示器终极配置指南

ParsecVDisplay:Windows虚拟显示器终极配置指南

ParsecVDisplay:Windows虚拟显示器终极配置指南 【免费下载链接】parsec-vdd ✨ Perfect virtual display for game streaming 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd 想要零成本扩展Windows电脑的显示空间?ParsecVDisplay为您…

2026/7/5 6:06:43阅读更多 →
中聚信财学院贵阳 AI 财务官实战营线下课顺利结束

中聚信财学院贵阳 AI 财务官实战营线下课顺利结束

2026/7/5 6:06:43阅读更多 →
Obsidian笔记图片本地化插件:如何彻底解决网络图片链接失效问题?

Obsidian笔记图片本地化插件:如何彻底解决网络图片链接失效问题?

Obsidian笔记图片本地化插件:如何彻底解决网络图片链接失效问题? 【免费下载链接】obsidian-local-images-plus This repo is a reincarnation of obsidian-local-images plugin which main aim was downloading images in md notes to local storage. …

2026/7/5 6:06:43阅读更多 →
WPS-Zotero插件:5分钟搞定跨平台文献引用,科研写作效率翻倍

WPS-Zotero插件:5分钟搞定跨平台文献引用,科研写作效率翻倍

WPS-Zotero插件:5分钟搞定跨平台文献引用,科研写作效率翻倍 【免费下载链接】WPS-Zotero An add-on for WPS Writer to integrate with Zotero. 项目地址: https://gitcode.com/gh_mirrors/wp/WPS-Zotero 还在为Windows和Linux之间切换文献管理软…

2026/7/5 6:06:43阅读更多 →
AAA小学期第五周学习笔记

AAA小学期第五周学习笔记

完成了发射端pcb的绘制,并下单

2026/7/5 6:01:43阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/5 0:01:08阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/5 0:01:08阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/5 0:01:08阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/5 0:01:08阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/5 0:01:08阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/5 0:01:08阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/5 1:30:27阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/5 3:48:10阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/5 3:48:09阅读更多 →