域驱动设计中的WCF序列化和Value对象模式 [英] WCF serialization and Value object pattern in Domain Driven Design

查看:69
本文介绍了域驱动设计中的WCF序列化和Value对象模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Eric Evans的《域驱动设计》一书描述了称为值对象的模式。价值对象的重要特征之一是它是不可变的。

The book Domain Driven Design by Eric Evans describes pattern called value object. One of the important characteristics of a value object is that it is immutable.

例如,我有一个值对象 Clinic,其中必须具有名称和ID。为了使其成为值对象,我不提供名称和ID的设置器。另外,为了确保没有无效的实例,我在构造函数中使用了名称和ID,并且没有在参数较少的构造函数中提供。

As an example I have a value object "Clinic" which must have a name and an id. To make it a value object I do not provide setters on name and id. Also to make sure that there is not invalid instance I take name and id in a constructor and do not provide at parameter less constructor.

公共类诊所
{

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

}

问题是,当我尝试从WCF服务返回此对象时,出现一个异常,即该对象没有较少的构造函数参数,而属性没有公共设置方法。我想避免添加较少的参数,而不是构造函数和公共设置器,因为那样的话,我的域模型模式就会出现问题。我该如何解决这个问题?

The problem is that when I try to return this object from a WCF Service I get an exception that the object does not have parameter less constructor and the properties do not have public setters. I want to avoid adding parameter less constructor and public setters because then my domain model pattern goes for a toss. How can I get around this problem?

问候,
Unmesh

Regards, Unmesh

推荐答案

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

I had a similar problem with serializing immutable types before, in the end I decided to implement the ISerializable interface and use the SerializationInfo to store & retrieve the private variables at both ends of the serialization/deserialization process:

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

我刚刚使用相同的技术构建并运行了一个测试应用,它似乎对我有用。因此,根据对您的诊所课程的更改,您可以将其更改为:

I just built and run a test app using the same technique and it seems to work for me. So in terms of changes to your Clinic class you could change it to:

[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)分开,在这种情况下,这是一个示例,说明了您可能如何使用它:

This will solve the problem you're having passing the data back from WCF. But from a design point of view, I agree with what Ladislav is saying and typically you will want to separate your domain objects with objects purely intended for message passing (DataTransferObjects), and in that case here's an example of how you MIGHT approach it:

// 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的痛苦,您可以添加一个诊所上的方法来执行此操作或实现隐式/显式转换器。我在这里有一个执行此操作的示例:
http://theburningmonk.com/2010/02/controlling-type-conversion-in-c/

To ease the pain of converting from Clinic to ClinicDTO, you could either add a method on Clinic to do this or implement an implicit/explicit converter. I've got an example on how to do this here: http://theburningmonk.com/2010/02/controlling-type-conversion-in-c/

希望这会有所帮助!

这篇关于域驱动设计中的WCF序列化和Value对象模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆