数据传输对象模式

时间:2013-02-06 08:30:18

标签: c# .net design-patterns dto

对不起,我是企业应用程序的新手以及设计模式。可能是这个问题缺乏对设计模式的了解。我发现使用DTO传输数据会更好。

我的业务实体类如下:

public class Patient
{    
    public string ID { get; set; }
    public string FullName { get; set; }
    public string FirstName { get; set; }
    public string Surname { get; set; }
}

所以在我的应用程序用户中只提供ID和HospitalID。所以它需要另一个Web服务并获取人员信息

 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; }
 }

所以基于这些信息我去了Patient对象。 (使用DTO模式)

所以我想写一个新类来转换它如下。

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;
    }
}

但是最近我读了很少articles 他们使用了Serializer Helper class以及XmlSerializer我无法理解为什么他们会使用这样的东西。

对于DTO模式是需要使用XmlSerializer以及为什么要使用它?

3 个答案:

答案 0 :(得分:20)

你应该看看AutoMapper。

http://automapper.org

这是一个软件,您可以将其包含在您的解决方案中,该软件会自动将值从一个类映射到另一个类。

它会自动映射具有相同名称的属性,并且在涉及子对象时也非常智能。但是,它还可在您需要时提供完整的映射控制。

修改

一些示例来说明AutoMapper的工作原理。请注意我在现实生活中从不编码。简洁!

示例类。

// 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; }
   }
}

通常,您可以使用项目的一部分来配置所有AutoMapping。通过我刚刚给出的示例,您可以在Entities.Manager和Models.Manager之间配置映射,如下所示: -

// Tell AutoMapper that this conversion is possible
Mapper.CreateMap<Entities.Manager, Models.Manager>();

然后,在您的代码中,您将使用类似的东西从实体版本中获取新的Models.Manager对象。

// Map the class
var mgr = Map<Entities.Manager, Models.Manager>
  ( repoManager, new Models.Manager() );

顺便提一下,如果你一致地命名,AM很聪明,可以自动解决很多属性​​。

上面的示例,应自动填充UserFirstname和UserLastname,因为: -

  • Manager有一个名为User
  • 的属性
  • 用户拥有名为Firstname和Lastname的属性

但是,在Entities.Manager和Models.Manager之间进行映射后,Models.Manager中的UserMiddlename属性将始终为空,因为User没有名为Middlename的公共属性。

答案 1 :(得分:3)

CodeProject中有一个很好但很简单的演示。值得通过它。 新手可以获得设计DTO的基本想法。

http://www.codeproject.com/Articles/8824/C-Data-Transfer-Object

以下是内容摘要:

数据传输对象&#34; DTO&#34;是一个简单的可序列化对象,用于跨应用程序的多个层传输数据。 DTO中包含的字段通常是原始类型,例如字符串,布尔值等。其他DTO可以包含在DTO中或聚合在一起。例如,您可能拥有LibraryDTO中包含的BookDTO集合。我创建了一个由多个应用程序使用的框架,这些应用程序利用DTO跨层传输数据。该框架还依赖于其他OO模式,例如Factory,Facade等。与DataSet相比,DTO的一大优点是DTO不必直接匹配数据表或视图。 DTO可以聚合来自另一个DTO的字段

这是所有数据传输对象的基类。

using System;

namespace DEMO.Common
{
/// This is the base class for all DataTransferObjects.
    public abstract class DTO
    {
        public 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;
        }
    }

}

这是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;
        }            
    }

}

现在开始序列化/反序列化:

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;
    }
}

最后,此代码在主应用程序中执行

static void Main(string[] args)
{
    DemoClass dc = new DemoClass();
    dc.StartDemo();
}

答案 2 :(得分:1)

XmlSerializer或JsonSerializer可用于从源(webservice)序列化(加载)XML或Json数据。或者解释名称DTO:您将数据从源(webservice)序列化(传输)到(一般DTO)对象。因此,DTO是通用对象。有时它很聪明地制作尽可能宽的DTO对象并完全填充它,这样你就可以从任何你喜欢的对象中使用它并将其复制到你自己的程序对象中。

示例:我开发了一个显示传输导航数据的程序。我在DTO对象中序列化整个xml或json的消息。在这个DTO对象中有更多的信息,然后我需要在我的程序中,它可以是一个不同的形式,所以我将只使用所需的。 DTO对象使得从源(webservices)中提取数据变得更加容易。

由于名称“Auto”,我不想使用AutoMapper。我想知道我在做什么,并想想我的数据将会发生在哪里。