【问题标题】:Passing models to - and from - service layer将模型传入和传出服务层
【发布时间】:2013-03-23 15:07:29
【问题描述】:

假设我有一个模型:

public class Thing
{
    public int? identifier { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    ... // arbitrary number of additional properties.
}

还有一个包含两个关键方法的服务层接口:

public interface IThingService
{
    Thing GetThing(int id);
    Thing AddThing(Thing thing);
}

现在,假设服务层会自动为AddThing 上的每个事物生成一个identifier。还假设将此identifier 公开给表示层很重要,因为它可能会传递给其他服务。

鉴于我必须将Thing 传递给AddThing,这是建模Thing 的最佳方式吗?表示层的开发者可能认为他们可以指定一个identifer,但这会被IThingService的具体实现忽略。当然identifier必须是public才能被IThingService设置为GetThing

是否可以简单地忽略在调用AddThing 时传递的identifier,或者是否有更好的方法对此进行建模以防止这种情况发生?

【问题讨论】:

    标签: c# architecture soa


    【解决方案1】:

    您的服务应如下所示:

    public interface IThingService
    {
        Thing GetThing(int id);
        ThingCreationResponse AddThing(ThingCreationRequest request);
    }
    

    ThingCreationRequest 将拥有创建Thing 实体所需的所有数据。它没有标识符。标识符将由AddThing 返回。

    AddThing 可以简单地返回一个Thing id,但在这种情况下,您应该提供一个有据可查的协议来传达错误(在失败的情况下返回负值,或抛出异常)。

    返回ThingCreationResponse 的实例将为您提供更好的灵活性,因为您可以返回新Thing 的id 或完整实例,也可以更好地传达失败原因。

    【讨论】:

      【解决方案2】:

      这仅在服务运行在原始Thing 实际存在的同一内存上时才有效。如果此服务断开连接,例如在另一台机器上,则更新 Thing 不会影响原始实例,identifier 将永远不会返回给调用代码。

      考虑到这一点,有 2 种可能的路径:您希望此服务始终在本地并在与调用应用程序相同的内存上运行,或者您希望此服务实际断开连接或最终断开连接。

      已连接

      如果已连接,此界面将正常工作,但您可能仍希望隐藏标识符的设置器。如果这样做,您可以将其设置为内部并在单独的程序集中定义服务接口和Thing 对象,这将使表示层无法访问设置器。好吧,您仍然可以通过反射或其他方式调用它,但对于典型的东西,它将无法访问。

      断开连接

      这个界面被破坏了,因为您无法以任何方式检索标识符,并且有必要检索现在保存的项目。此处的典型解决方案将返回来自 AddThing 方法的标识符,或者如果它足够小,则返回整个对象(新内存)。

      除此之外,不可变数据项很难推理,无论哪种情况,我都可能更愿意在调用AddThing 之后创建一个新的Thing

      【讨论】:

      • 嗨尼克,我已经修改了我的问题,以便AddThing 返回Thing 的新实例(无论如何,这就是它在应用程序中的实际建模方式)。那么您认为将identifier 定义为public int? identifier { get; internal set; } 是否合适?如果IThingServiceThing 在同一个程序集中定义,但ActualThingService 有自己的程序集怎么办?
      【解决方案3】:

      我认为在这种情况下,AddThing 的正确签名将是 AddThing(string title, string description),并且该方法的职责是使用生成的标识符构建 Thing 对象。

      考虑到您的最后一个规范,我建议创建第二个类,ThingWithId 作为成员标识符和 Thing。 AddThing 的签名将更改为 ThingWithId AddThing(Thing thing)

      【讨论】:

      • 感谢您的回复 - 这原本是计划;但是,Thing 可能比两个属性复杂得多 - 应该在问题中明确说明。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      • 2011-07-06
      • 2023-03-18
      相关资源
      最近更新 更多