1

好的,所以我参与了创建 DTO 以通过网络发送我的模型的漫长过程的一部分,我不觉得我走的是正确的路线。

我的问题是,我模型中的大多数实体无论如何都没有 DTO 多。我基本上有一个贫血的域模型,这很好,但它也让我想知道我是否需要为这些实体建模 DTO。

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

其次,给出了一个更具体的问题,如下所示:

public virtual Unit Unit { get; set; }

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

编辑:对不起,我的问题不够清楚,正如你们发布的那样,我知道我只能指定单元的 Id 属性,但这对我不起作用。

原因是该属性(上图)位于“Country”类上,我希望 UnitID 仅在调用“CountryService.GetCountry(Id)”或类似名称时返回。但是在流动的服务调用“UnitService.GetUnit(Id)”上,我希望更多的属性被序列化并通过网络发送。希望这是有道理的。

谢谢,克里斯。

4

3 回答 3

1

其次,给出了一个更具体的问题,如下所示:

public virtual Unit Unit { get; set; }

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

当然 - 确保

  1. 不要Unit[DataMember]
  2. 创建第二个属性UnitId,您将其标记为数据成员
  3. 确保您的客户总能以某种方式重建Unit课程UnitId

更新:

原因是该属性(上图)位于“Country”类上,我希望 UnitID 仅在调用“CountryService.GetCountry(Id)”或类似名称时返回。但是在流动的服务调用“UnitService.GetUnit(Id)”上,我希望更多的属性被序列化并通过网络发送。希望这是有道理的。

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

您不能有条件地发送某些属性(或不发送),具体取决于运行时决定。DataContracts 在 XML 模式中建模,这是相当静态的。如果您需要两组属性,则需要两个单独的 DataContract。

于 2009-11-13T14:23:56.017 回答
0

您可以通过添加 NonSerializedAttribute ( msdn )缩小将通过线路传递的对象的大小。您仍然会得到 Unit,但只能使用 UnitId。

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

于 2009-11-13T14:30:44.713 回答
0

据我所知,您的问题源于您有一个由 DTO 制成的本地明确声明的对象图。我的意思是你已经public Unit Unit { get; set; }在你的Country模型上声明了(不知道你为什么要声明它们virtual,但这与手头的问题没有直接关系),而不是尝试一种方法来保证对象图的简单性变成单一的退化情况对象图节点。

例如,考虑以实际可能存在的形式或用于唯一标识和区分的任何形式定义模型上的每个引用”属性public UnitID Unit { get; set; }UnitIDintGuidUnit彼此的模型。无论您在哪里有对另一个模型的引用或一组引用,都将其替换为其标识符类型而不是其实际类型。这种策略很适合一组持久化的模型,例如从/到每个模型都有身份密钥的数据库。这样做可以让您简化序列化,而不必担心循环引用,因为它们现在是不可能的。从技术上讲,不再有引用(即直接引用;它们现在是间接引用)。我们现在只是在您的域模型设计中添加一个间接层。现在让我们适应那个间接层。

既然你声称你对贫血域模型方法没问题,那么这应该很适合。您在模型设计中支付次要(恕我直言)间接成本,并将其换成基于接口的数据检索方法的主要(恕我直言)好处:

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>SomeUnitsRepositoryImpl.

有点啰嗦,但希望对你有帮助。好像从所提供的细节数量上看不明显,我目前正在我的工作地点玩弄这种设计,以处理我们的记录数据库系统。:) 我真的很喜欢它给我的所有灵活性,而代价是在域模型的设计中添加一层间接性。

于 2009-12-20T06:35:33.817 回答