代码之家  ›  专栏  ›  技术社区  ›  Unmesh Kondolikar

领域驱动设计中的WCF序列化和值对象模式

  •  3
  • Unmesh Kondolikar  · 技术社区  · 15 年前

    必须

    公立诊所 {

    public Clinic(string name, string id)
    {
        Name = name;
        Id = id;  
    }
    
    public string Name{get; private set;}
    public string Id{get; private set;}
    

    }

    问题是,当我尝试从WCF服务返回这个对象时,我得到一个异常,即该对象没有无参数构造函数,并且属性没有公共setter。我希望避免添加无参数构造函数和公共设置器,因为这样我的域模型模式就很麻烦了。我怎样才能避开这个问题?

    当做,

    2 回复  |  直到 15 年前
        1
  •  3
  •   theburningmonk    15 年前

    在序列化不可变类型之前,我也遇到过类似的问题,最后我决定实现ISerializable接口,并使用SerializationInfo在序列化/反序列化过程的两端存储和检索私有变量:

    http://theburningmonk.com/2010/04/net-tips-making-a-serializable-immutable-struct/

    我刚刚用同样的技术构建并运行了一个测试应用程序,它似乎对我有用。所以你可以把你的诊所课程改成:

    [Serializable]
    public class Clinic : ISerializable
    {
    public Clinic(string name, string id)
    {
        Name = name;
        Id = id;  
    }
    
    public Clinic(SerializationInfo info, StreamingContext context)
    {
        Name= info.GetString("Name");
        Id= info.GetString("Id");
    }
    
    public string Name{get; private set;}
    public string Id{get; private set;}
    
    [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Name", Name);
        info.AddValue("Id", Id);
    }
    }
    

    这将解决从WCF传回数据的问题。但从设计的角度来看,我同意Ladislav所说的,通常您会希望将域对象与纯粹用于消息传递的对象(DataTransferObjects)分开,在这种情况下,下面是一个示例,说明如何处理它:

    // the domain object (NOT EXPOSED through the WCF service)
    public class Clinic
    {
    public Clinic(string name, string id)
    {
        Name = name;
        Id = id;  
    }
    
    public string Name{ get; private set;}
    public string Id{ get; private set;}
    
    // other methods encapsulating some business logic, etc.
    ...
    }
    // the corresponding DTO object for the domain object Clinic
    // this is the type exposed through the WCF layer, that the client knows about
    [DataContract]
    public class ClinicDTO
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Id { get; set; }
    }
    // WCF service contract, NOTE it returns ClinicDTO instead of Clinic
    [ServiceContract]
    public interface IClinicService
    {
       [OperationContract]
       ClinicDTO GetClinicById(string id);
    }
    

    为了减轻从Clinic转换到ClinicDTO的痛苦,您可以在Clinic上添加一个方法来执行此操作,或者实现隐式/显式转换器。我举了一个例子来说明如何做到这一点: http://theburningmonk.com/2010/02/controlling-type-conversion-in-c/

    希望这有帮助!

        2
  •  2
  •   Ladislav Mrnka    15 年前

    如果你想拥有真正的域驱动设计,你不应该在WCF中公开你的域对象。相反,您应该创建一组DTO并公开这些DTO。服务层将负责将这些DTO转换为域对象/值对象,反之亦然。

    推荐文章