WCF DataMember序列化问题

时间:2009-11-13 14:16:05

标签: wcf serialization datamember

好的,所以我在创建DTO以通过电线发送我的模型的漫长过程中处于中途,我不觉得我走的是正确的路线。

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

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

其次,一个更具体的问题给出了如下属性签名:

public virtual Unit Unit { get; set; }

我可以通过线路发送UnitId而不是序列化的单元对象吗?

修改: 对不起我对我的问题不够清楚,因为你们发布了我知道我只能指定单位的Id属性,但这对我不起作用。

原因是这个属性(上面)位于“Country”类上,我希望UnitID仅在我调用“CountryService.GetCountry(Id)”或simmilar时返回。但是在floowing服务调用“UnitService.GetUnit(Id)”中,我希望通过网络序列化和发送更多属性。 希望这是有道理的。

谢谢,克里斯。

3 个答案:

答案 0 :(得分:1)

  
    

其次,一个更具体的问题给出了如下属性签名:

         

public virtual Unit Unit { get; set; }

         

我是否可以通过电线发送UnitId和     不是序列化的单位对象?

  

当然 - 确保

  1. 未使用Unit
  2. 标记您的[DataMember]媒体资源
  3. 创建名为UnitId的第二个属性,您执行标记为数据成员
  4. 确保您的客户始终能够以某种方式重建Unit课程UnitId
  5. 更新:

      

    原因是这个属性   (上)是在“国家”级和我   希望UnitID仅在我返回时返回   调用“CountryService.GetCountry(Id)”   或者类似的。但是在飞行中   服务调用“UnitService.GetUnit(Id)”   我想要更多的属性   序列化并通过电线发送。   希望这是有道理的。

    在这种情况下,您需要两个单独的DataContracts - 一个用于CountryService.GetCountry(Id)调用,其中只包含UnitId,另一个用于UnitService.GetUnit(Id)调用,其所有属性均为{ {1}}你想要它。

    根据运行时的决定,您无法有条件地发送某些属性 - 或者不发送。 DataContracts以XML模式建模,这是非常静态的。如果您有两组需要的属性,则需要两个单独的DataContracts。

答案 1 :(得分:0)

您可以通过添加NonSerializedAttribute(msdn)来缩小将通过网络传递的对象。您仍将获得Unit,但仅限于UnitId。

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

答案 2 :(得分:0)

根据我的理解,您的问题源于您有一个由您的DTO制作的本地显式声明的对象图。我的意思是你已经在你的public Unit Unit { get; set; }模型上声明Country(不确定为什么你宣布它们virtual但这与手头的问题没有直接关系)而不是尝试保证对象图简单到单个对象图节点的退化情况的方法。

例如,考虑在public UnitID Unit { get; set; }形式的模型中定义每个“reference”属性,其中UnitID可能实际为int或{{1}或者你用来唯一地识别和区分Guid模型的任何东西。只要您有对另一个模型的引用或引用集,请将其替换为其标识符类型而不是其实际类型。这种策略很适合一组持久的模型,例如:从/到具有每个模型的标识键的数据库。这样做可以简化序列化,而不必担心循环引用,因为它们现在是不可能的。从技术上讲,没有更多的引用(即直接引用;它们现在是间接引用)。我们现在只是在您的域模型设计中添加一层间接。现在让我们适应那个间接层。

既然你声称你对贫血领域模型方法很好,那么这应该与之相符。您在模型设计中支付次要(IMHO)间接成本,并将其换成基于接口的数据检索方法的主要(IMHO)优势:

Unit

在您的消费者代码中(即使用此接口的代码和您的public interface IUnitRepository { Unit GetUnit(UnitID id); IEnumerable<Unit> GetUnits(IEnumerable<UnitID> ids); // etc. } 域模型),通过执​​行接口调用以获取指向的基础模型,遍历隐含对象图只会稍微复杂一些。间接参考。

在:

Unit

在:

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

如果这在语法上困扰你,你可以定义一个在表单的// 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)实例绑定的Dictionary<UnitID, Unit>执行一些本地内存缓存。

有点啰嗦,但我希望它有所帮助。好像从提供的细节数量来看并不明显,我目前正在我的工作场所使用这种设计处理我们的记录数据库系统。 :)我非常喜欢它给我所有的灵活性,只需在领域模型的设计中添加一个间接级别的简单成本。