19

对不起,我是企业应用程序和设计模式的新手。可能是这个问题缺乏对设计模式的了解。我发现使用 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; }
 }

所以基于这些信息我要去病人对象。(使用 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;
    }
}

但最近我读了几篇文章,他们使用Serializer Helper class得很好,XmlSerializer我不明白他们为什么使用这样的东西。

对于 DTO 模式来说,需要使用 XmlSerializer,为什么要使用它?

4

3 回答 3

27

你真的应该看看 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 的公共属性。

于 2013-02-06T08:33:04.083 回答
4

CodeProject 中有一个不错但简单的演示。值得通过它。新手可以对设计 DTO 有一个基本的了解。

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

以下是内容摘要:

数据传输对象“DTO”是一个简单的可序列化对象,用于跨应用程序的多个层传输数据。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();
}
于 2015-04-23T04:43:54.800 回答
2

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

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

由于名称为“Auto”,我不想使用 AutoMapper。我想知道我在做什么,并想我的数据要去哪里。

于 2013-10-02T10:59:02.510 回答