C# 数据传输对象模式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14724612/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Data transfer object pattern
提问by DevT
i'm sorry i'm newbie to enterprise application as well as the design pattern. might be this question occcur lack of knowledge about design pattern. i found that its better to use DTO to transfer data.
对不起,我是企业应用程序和设计模式的新手。可能是这个问题对设计模式缺乏了解。我发现使用 DTO 传输数据更好。
my business entity class as below:
我的业务实体类如下:
public class Patient
{
public string ID { get; set; }
public string FullName { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
}
so in my application user only give ID and HospitalID. so it calls for another web service and get person information
所以在我的应用程序中,用户只提供 ID 和 HospitalID。所以它需要另一个网络服务并获取个人信息
public class PersonDTO
{
public string NIC { get; set; }
public string FullName { get; set; }
public string FirstName { get; set; }
public string BirthPlace { get; set; }
public string BirthCertificateID { get; set; }
}
so based on these information im going to Patient object. (Using DTO pattern)
因此,根据这些信息,我将转到 Patient 对象。(使用 DTO 模式)
so i thought of write new class to convert this as follows.
所以我想写一个新的类来转换它如下。
public class PatientDO
{
public static Patient ConvertToEntity(
PatientRegistrationDTO pregDTO,
PersonDTO person
)
{
Patient p = new Patient();
p.NIC = pregDTO.NIC;
p.FullName = person.FullName;
p.FirstName = person.FirstName;
return p;
}
}
but lately i read few articles and they used Serializer Helper class
as well as the XmlSerializer
i can't understand why they used somthing like that.
但最近我读了几篇文章,他们使用Serializer Helper class
了以及XmlSerializer
我不明白为什么他们使用这样的东西。
for the DTO pattern is that need to use XmlSerializer and why it is used?
对于 DTO 模式,需要使用 XmlSerializer 以及为什么使用它?
采纳答案by Paul Alan Taylor
You should really take a look at AutoMapper.
你真的应该看看 AutoMapper。
This is a piece of software that you can include in your solution that will automatically map values from one class to another.
这是一款可以包含在解决方案中的软件,它会自动将值从一个类映射到另一个类。
It'll map properties with the same name automatically, and is also pretty smart when it comes to child objects. However, it also offers complete mapping control when you need it.
它将自动映射具有相同名称的属性,并且在涉及子对象时也非常聪明。但是,它还在您需要时提供完整的映射控制。
EDIT
编辑
Couple of examples to show how AutoMapper works. Please note I'd never code like this in real life. Brevity!
几个例子来展示 AutoMapper 的工作原理。请注意,我在现实生活中绝不会像这样编码。简洁!
Example classes.
示例类。
// Common scenario. Entity classes that have a connection to the DB.
namespace Entities
{
public class Manager
{
public virtual int Id { get; set; }
public virtual User User { get; set; }
public virtual IList<User> Serfs { get; set; }
}
public class User
{
public virtual int Id { get; set; }
public virtual string Firstname { get; set; }
public virtual string Lastname { get; set; }
}
}
// Model class - bit more flattened
namespace Models
{
public class Manager
{
public int Id { get; set; }
public string UserFirstname { get; set; }
public string UserLastname { get; set; }
public string UserMiddlename { get; set; }
}
}
Typically, you'd have a part of your project to configure all your AutoMapping. With the examples I've just given, you can configure a map between Entities.Manager and Models.Manager like so:-
通常,您将拥有项目的一部分来配置所有 AutoMapping。通过我刚刚给出的示例,您可以像这样配置 Entities.Manager 和 Models.Manager 之间的映射:-
// Tell AutoMapper that this conversion is possible
Mapper.CreateMap<Entities.Manager, Models.Manager>();
Then, in your code, you'd use something like this to get a new Models.Manager object from the Entity version.
然后,在您的代码中,您将使用类似的方法从实体版本中获取新的 Models.Manager 对象。
// Map the class
var mgr = Map<Entities.Manager, Models.Manager>
( repoManager, new Models.Manager() );
Incidentally, AM is smart enough to resolve a lot of properties automatically if you name things consistently.
顺便说一句,如果您一致地命名事物,AM 足够聪明,可以自动解析许多属性。
Example above, UserFirstname and UserLastname should be automatically populated because:-
上面的例子, UserFirstname 和 UserLastname 应该自动填充,因为:-
- Manager has a property called User
- User has properties called Firstname and Lastname
- Manager 有一个名为 User 的属性
- 用户具有名为 Firstname 和 Lastname 的属性
However, the UserMiddlename property in Models.Manager will always be blank after a mapping op between Entities.Manager and Models.Manager, because User does not have a public property called Middlename.
但是,在 Entities.Manager 和 Models.Manager 之间的映射操作之后,Models.Manager 中的 UserMiddlename 属性将始终为空,因为 User 没有名为 Middlename 的公共属性。
回答by Herman Van Der Blom
An XmlSerializer or JsonSerializer can be used for serializing (loading) XML or Json data from a source (webservice). Or explaining the name DTO: you serialize (transfer) data from a source (webservice) to a (general DTO) object. So DTOs are general purpose objects. Sometimes its clever to make a wide as possible DTO object and fill that completely so you can use from that object whatever you like and copy that to your "own" program objects.
XmlSerializer 或 JsonSerializer 可用于从源(网络服务)序列化(加载)XML 或 Json 数据。或解释 DTO 名称:您将数据从源(网络服务)序列化(传输)到(通用 DTO)对象。所以 DTO 是通用对象。有时,制作一个尽可能宽的 DTO 对象并完全填充它是很聪明的,这样您就可以从该对象中使用任何您喜欢的内容并将其复制到您的“自己的”程序对象中。
Example: I developped a program for showing transport navigation data. I serialize the whole xml or json messsage in a DTO object. In this DTO object is more information then I will need in my program and it can be in a different form, so I will use only whats needed. DTO objects makes it more easy to extract data from sources (webservices).
示例:我开发了一个显示交通导航数据的程序。我在 DTO 对象中序列化整个 xml 或 json 消息。在这个 DTO 对象中有更多的信息,然后我将在我的程序中需要它,它可以是不同的形式,所以我将只使用需要的信息。DTO 对象使从源(网络服务)中提取数据变得更加容易。
I dont want to use AutoMapper because of the name "Auto". I want to know what I am doing and think where my data is going to.
由于名称“Auto”,我不想使用 AutoMapper。我想知道我在做什么并思考我的数据要去哪里。
回答by Venugopal M
There is a nice, yet simple demo in CodeProject. It is worthy going through it. Newbies can get a basic idea of designing DTOs.
CodeProject 中有一个很好但简单的演示。值得经历它。新手可以对设计 DTO 有一个基本的了解。
http://www.codeproject.com/Articles/8824/C-Data-Transfer-Object
http://www.codeproject.com/Articles/8824/C-Data-Transfer-Object
Here's a summary of the content:
以下是内容摘要:
The Data Transfer Object "DTO", is a simple serializable object used to transfer data across multiple layers of an application. The fields contained in the DTO are usually primitive types such as strings, boolean, etc. Other DTOs may be contained or aggregated in the DTO. For example, you may have a collection of BookDTOs contained in a LibraryDTO. I have created a framework used by multiple applications that utilizes DTOs to transfer data across tiers. The framework also relies on other OO patterns such as the Factory, Facade, etc. One of the great things about the DTO compared to a DataSet is that the DTO does not have to directly match a data table or view. The DTO can aggregate fields from another DTO
数据传输对象“DTO”是一个简单的可序列化对象,用于跨应用程序的多个层传输数据。DTO 中包含的字段通常是原始类型,例如字符串、布尔值等。其他 DTO 可能包含或聚合在 DTO 中。例如,您可能有一个包含在 LibraryDTO 中的 BookDTO 集合。我创建了一个由多个应用程序使用的框架,该框架利用 DTO 跨层传输数据。该框架还依赖于其他 OO 模式,例如 Factory、Facade 等。与 DataSet 相比,DTO 的一大优点是 DTO 不必直接匹配数据表或视图。DTO 可以聚合来自另一个 DTO 的字段
This is the base class for all Data Transfer Objects.
这是所有数据传输对象的基类。
using System;
namespace DEMO.Common
{
/// This is the base class for all DataTransferObjects.
public abstract class DTO
{
public DTO()
{
}
}
}
This is a derived class from DTO:
这是 DTO 的派生类:
using System;
using System.Xml.Serialization;
using DEMO.Common;
namespace DEMO.DemoDataTransferObjects
{
public class DemoDTO : DTO
{
// Variables encapsulated by class (private).
private string demoId = "";
private string demoName = "";
private string demoProgrammer = "";
public DemoDTO()
{
}
///Public access to the DemoId field.
///String
[XmlElement(IsNullable=true)]
public string DemoId
{
get
{
return this.demoId;
}
set
{
this.demoId = value;
}
}
///Public access to the DemoId field.
///String
[XmlElement(IsNullable=true)]
public string DemoName
{
get
{
return this.demoName;
}
set
{
this.demoName = value;
}
}
///Public access to the DemoId field.
///String
[XmlElement(IsNullable=true)]
public string DemoProgrammer
{
get
{
return this.demoProgrammer;
}
set
{
this.demoProgrammer = value;
}
}
}
This is the helper class for a DTO. It has public methods to serialize and de-serialize a DTO.
这是 DTO 的辅助类。它具有序列化和反序列化 DTO 的公共方法。
using System;
using System.Xml.Serialization;
using System.IO;
namespace DEMO.Common
{
public class DTOSerializerHelper
{
public DTOSerializerHelper()
{
}
///
/// Creates xml string from given dto.
///
/// DTO
/// XML
public static string SerializeDTO(DTO dto)
{
try
{
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
// Serialize the dto to xml.
xmlSer.Serialize(sWriter, dto);
// Return the string of xml.
return sWriter.ToString();
}
catch(Exception ex)
{
// Propogate the exception.
throw ex;
}
}
///
/// Deserializes the xml into a specified data transfer object.
///
/// string of xml
/// type of dto
/// DTO
public static DTO DeserializeXml(string xml, DTO dto)
{
try
{
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
// Read the XML.
StringReader sReader = new StringReader(xml);
// Cast the deserialized xml to the type of dto.
DTO retDTO = (DTO)xmlSer.Deserialize(sReader);
// Return the data transfer object.
return retDTO;
}
catch(Exception ex)
{
// Propogate the exception.
throw ex;
}
}
}
Now begin Serialization / Deserialization:
现在开始序列化/反序列化:
using System;
using DEMO.Common;
using DEMO.DemoDataTransferObjects;
namespace DemoConsoleApplication
{
public class DemoClass
{
public DemoClass()
{
}
public void StartDemo()
{
this.ProcessDemo();
}
private void ProcessDemo()
{
DemoDTO dto = this.CreateDemoDto();
// Serialize the dto to xml.
string strXml = DTOSerializerHelper.SerializeDTO(dto);
// Write the serialized dto as xml.
Console.WriteLine("Serialized DTO");
Console.WriteLine("=======================");
Console.WriteLine("\r");
Console.WriteLine(strXml);
Console.WriteLine("\r");
// Deserialize the xml to the data transfer object.
DemoDTO desDto =
(DemoDTO) DTOSerializerHelper.DeserializeXml(strXml,
new DemoDTO());
// Write the deserialized dto values.
Console.WriteLine("Deseralized DTO");
Console.WriteLine("=======================");
Console.WriteLine("\r");
Console.WriteLine("DemoId : " + desDto.DemoId);
Console.WriteLine("Demo Name : " + desDto.DemoName);
Console.WriteLine("Demo Programmer: " + desDto.DemoProgrammer);
Console.WriteLine("\r");
}
private DemoDTO CreateDemoDto()
{
DemoDTO dto = new DemoDTO();
dto.DemoId = "1";
dto.DemoName = "Data Transfer Object Demonstration Program";
dto.DemoProgrammer = "Kenny Young";
return dto;
}
}
Finally this code is executed in the main application
最后这段代码在主应用程序中执行
static void Main(string[] args)
{
DemoClass dc = new DemoClass();
dc.StartDemo();
}