2009-11-13 91 views
1

好的,所以我参与了创建DTO的漫长过程,以便通过电线发送我的模型,我不觉得我要走正确的路线。WCF DataMember序列化问题

我的问题是,我的模型中的大部分实体并不多于DTO。我基本上有一个贫血的领域模型,这很好,但它也让我想知道是否需要为这些实体建模DTO。

所以,我的第一个问题是,如果只是序列化我的实体并通过线路传递这些信息,可能会遇到什么问题?

其次,一个更具体的问题给出像这样的属性签名:

public virtual Unit Unit { get; set; } 

是否有可能,我只是在导线上的单元ID而不是序列化单元对象发送?

编辑: 对不起,我不清楚我的问题,因为你们发布我知道我只能指定单位的Id属性,但这不会为我工作。

原因是这个属性(上面)是在“Country”类上的,我希望UnitID只在我调用“CountryService.GetCountry(Id)”时才会返回或类似。但在浮动服务调用“UnitService.GetUnit(Id)”我想要更多的属性被序列化并通过电线发送。 希望这是有道理的。

谢谢,克里斯。

回答

1

其次,一个更具体的问题给出一个属性签名像这样:

public virtual Unit Unit { get; set; }

是否有可能,我只是把线路上的UnitID和 不序列化单元发送目的?

当然 - 确保

  1. 没有标记您Unit财产与[DataMember]
  2. 创建一个名为UnitId第二个属性,你马克数据成员
  3. 确保你的客户总是可以从以某种方式重建Unit

UPDATE:

的原因是,这家酒店 (上图)是一个 “国家” 级和我 希望的UnitID只返回时,我 呼叫“CountryService.GetCountry (Id)“ 或simmilar。但在浮动 服务调用“UnitService。GetUnit(ID)” 我想更多的属性是 序列化并通过网络发送 希望这是有道理

在这种情况下,你需要两个独立的DataContracts - 。一个是CountryService.GetCountry(Id)呼叫只用在它UnitId,和另一个用于UnitService.GetUnit(Id)通话用的Unit所有属性要在它

无法有条件地发送一些特性 - 与否 - 这取决于运行时决定DataContracts在XML架构为蓝本,如果你有两套你需要的属性,y您需要两个独立的DataContracts。

0

通过添加NonSerializedAttribute(msdn),可以缩小将通过电线传递的对象的大小。你仍然会得到Unit,但只有UnitId。

我不认为只是序列化你的DTO会有问题。 您是否使用DTO中的所有信息? 你是否跨越了域界限?我会在每个域中创建新的实体并为它们制作映射器。

0

从我所能理解的,你的问题源于你有一个由你的DTO制作的本地显式声明的对象图的事实。我的意思是你已经在你的Country模型上声明public Unit Unit { get; set; }(不知道你为什么声明它们是virtual,但这与手头的问题没有直接关系),而不是尝试一种方法来保证对象图简化为简并案例的单个对象图节点。

例如,考虑形式public UnitID Unit { get; set; }定义“参照”财产上的模型,其中UnitID实际上可能intGuid或者你用它来相互唯一识别和区分Unit模型。只要你有一个引用或一组引用另一个模型,用它的标识符类型而不是它的实际类型替换它。这种策略适用于一套持久的模型,例如从/到每个模型具有身份密钥的数据库。这样做可以让你简单的序列化,而不必担心循环引用,因为它们现在是不可能的。从技术上讲,没有更多的引用(即直接引用;它们现在是间接引用)。我们现在只是在您的领域模型设计中添加一个间接层。现在我们来适应那个间接层。

既然你声称你对贫血域模型方法很好,那么这应该与此相适应。你付出的间接的未成年人(恕我直言)成本模型的设计和交易它的主要(恕我直言)基于接口的方法的好处数据检索:

public interface IUnitRepository { 
    Unit GetUnit(UnitID id); 
    IEnumerable<Unit> GetUnits(IEnumerable<UnitID> ids); 
    // etc. 
} 

在你的消费者的代码(即代码使用此接口和域模型),通过执​​行接口调用以获取由间接引用指向的基础模型来遍历隐含对象图只会稍微复杂一些。

BEFORE:

Country ct = ...; // I assume you have this reference already 
Unit ut = ct.Unit; 

AFTER:

// Somewhere earlier in your code, i.e. not *every* time this type of code appears 
IUnitsRepository repo = new SomeUnitsRepositoryImpl(); 
Country ct = ...; // I assume you have this reference already 
Unit ut = repo.GetUnit(ct.UnitID); 

如果这句法困扰你,你可以定义上键入形式的Country一套扩展的方法:

public static Unit Unit(this Country c, IUnitsRepository repo) { 
    return repo.GetUnit(c.UnitID); 
} 

扩展方法后:

IUnitsRepository repo = new SomeUnitsRepositoryImpl(); 
Country ct = ...; // I assume you have this reference already 
Unit ut = ct.Unit(repo); 

基于接口的方法可以为您带来经典的一系列优点,如关注点分离,可测试性,消费者与生产者绝缘等等。此外,您现在可以通过接口的实现类型更直接地控制对象的生命周期。我的意思是,你不应该假设你的Unit GetUnit(UnitID id)方法的实施是天真的。此方法现在可以使用与SomeUnitsRepositoryImpl的实例绑定的Dictionary<UnitID, Unit>执行一些本地内存缓存。

有点啰嗦,但我希望它有帮助。仿佛从提供的细节数量来看,这并不明显,我目前正在我的工作地点开展这项设计,以处理我们的记录数据库系统。 :)我真的非常喜欢它给我所有的灵活性,只需在域模型的设计中增加一层间接寻址的简单代价。

+0

好吧,所以属性是虚拟的原因是因为我正在使用和ORM(NHibernate在这种情况下),它需要我的POCO国家对象,并围绕它建立一个代理来自动挂钩延迟加载相关对象(即单位这个案例)。现在,我可以让Country对象与您声明的任何其他模型没有关系,但这意味着要手动创建所有这些管道工作。这对我来说不是一个好的折衷,因为我认为序列化程序应该足够灵活,可以让我采用复杂的模型,只显示我选择的内容。我最终选择了AutoMapper – Owen 2009-12-21 23:06:25