DTO 的 Live 应该在哪个项目层进行屏蔽?

发布于 2024-07-12 14:05:14 字数 1434 浏览 5 评论 0原文

我有一个项目,我们使用屏幕 DTO 来封装服务层表示层之间的数据。 在我们的例子中,表示层是 ASP.Net。

唯一了解 DTO 的类是服务层类以及调用这些服务并显示 DTO 的页面/控件。

DTO 几乎总是特定于页面/控制的,因此我觉得它们属于表示层,但这意味着服务层必须引用表示层才能使用 DTO。

我几乎认为服务层应该返回更丰富的对象(但不是域实体?),然后表示层可以获取这些对象并将它们映射到每个页面/控件关注点的非常特定的 DTO。

这是一个接口声明和一个 DTO,以便您可以了解我在说什么:

public interface IBlogTasks
{
    BlogPostDisplayDTO GetBlogEntryByTitleAndDate(int year, int month, string urlFriendlyTitle);
}

public class BlogPostDisplayDTO 
{
    public string Title { get; set; }
    public DateTime PostDate { get; set; }
    public string HtmlContent { get; set; }
    public string ImageUrl { get; set; }        
    public string Author { get; set; }
    public int CommentCount { get; set; }
    public string Permalink { get; set; }
}   

编辑

这是另一个代码示例,用于描述不涉及域模型的用例。 也许这会让事情变得更清楚一些。 我相信我已经超载了 DTO 的含义。 我不是在谈论用于通过线路传输对象的功能的 DTO。 我正在创建 DTO 来正式确定与服务层的通信之间的合同。

public interface IAuthenticationTasks
{
    bool AuthenticateUser(AuthenticationFormDTO authDTO);
}

public class AuthenticationFormDTO
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool persistLogin { get; set; }
}

假设我的身份验证突然需要 IP 地址参数。 我现在可以将该属性添加到 DTO,而无需更改我的合约接口。

我不想将实体传递到我的表示层。 我不希望我的后台代码能够执行 BlogPost.AddComment(new Comment())

I have a project where we use screen DTO's to encapsulate the data between the Service Layer and the Presentation Layer. In our case, the presentation layer is ASP.Net.

The only classes that know about the DTO's are the service layer classes and the Pages/Controls that call these services and display the DTO's.

The DTO's are almost always Page/Control specific so I feel they belong in the Presentation Layer, but that would mean the Service Layer would have to reference the Presentation Layer in order to use the DTO's.

I'm almost thinking that the Service Layer should return richer objects (but not domain entities?) and then the Presentation Layer can take these objects and map them to very specific DTO's for each Page/Control concern.

Here's an interface declaration and a DTO so you can see what I'm talking about:

public interface IBlogTasks
{
    BlogPostDisplayDTO GetBlogEntryByTitleAndDate(int year, int month, string urlFriendlyTitle);
}

public class BlogPostDisplayDTO 
{
    public string Title { get; set; }
    public DateTime PostDate { get; set; }
    public string HtmlContent { get; set; }
    public string ImageUrl { get; set; }        
    public string Author { get; set; }
    public int CommentCount { get; set; }
    public string Permalink { get; set; }
}   

Edit

Here's another code sample to describe a use case where the Domain model isn't involved. Maybe this will clarify things a bit. I believe I've overloaded the DTO meaning. I'm not talking about a DTO for the function of transfering an object over the wire. I'm creating DTOs to formalize contracts between communication to my Service Layer.

public interface IAuthenticationTasks
{
    bool AuthenticateUser(AuthenticationFormDTO authDTO);
}

public class AuthenticationFormDTO
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool persistLogin { get; set; }
}

Let's say my authentication all of the sudden requires an IP address parameter. I can now add that property to the DTO without having to change my contract interface.

I don't want to pass Entities to my Presentation Layer. I don't want my code behind to have the ability to go BlogPost.AddComment(new Comment())

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

八巷 2024-07-19 14:05:14

即使认为“DTO”的规范用例更多是“可以通过线路传递的可序列化对象”,在这种情况下,您实际上更多地指的是“演示传输对象”或“视图模型”。

通常,对于我们的项目来说,这些存在的答案是将 DDD 域模型映射到 PTO 类的“翻译”代码所在的位置。 如果那是在 Preensenation 层中(也许不是一个很好的答案),那么 pres. 层是我声明 PTO 的地方。 但通常情况下,“服务”会为您进行翻译,这意味着“服务”层和“表示”层都需要对 PTO 的引用,并且(通常)导致它们在单独的、中立的项目/程序集/命名空间/表示层和服务层都可以引用的任何内容。

Even thought the canonical use-case for the 'DTO' is more "serializable object that can be passed over the wire", in this case you are really referring more to 'presentation-transfer-objects' or 'view-models'.

Typically for our projects the answer to where these live is where the 'translation' code is that maps the DDD domain model to the PTO classes. If that's in the Prensenation layer (perhaps not so great an answer) then the pres. layer is where I'd declare the PTOs. But more often than not, its the 'Service' that does the translation for you and that means that both the 'Service' and the 'Presentation' layer need references to the PTOs and that (usually) leads to their declaration in a separate, neutral project/assembly/namespace/whatever that BOTH the presentation layer AND the service layer can then reference.

貪欢 2024-07-19 14:05:14

您是否使用实际的服务(Web 或 WCF)? 如果是这样,则在服务层中定义 DTO,并且在添加服务(或 Web,如果使用旧 ASMX)引用时创建的代理将包含所有 DTO 类型。 这是最简单的方法,并且只维护 ASP.NET 项目和服务项目之间的松散耦合——任一方向都不需要直接的项目引用。 当您更新 DTO 时,您所需要做的就是更新服务引用,它将通过生成的代理类自动将更新公开到您的 Web 项目。

无论如何,如果您遵循 DDD 方法之类的方法,那么最好让您的基础设施项目(例如特定于 Web 平台的 UI)引用您的域对象,而不是反之亦然。 但是,如果您遵循我上面的建议,您的 Web 项目将根本不会直接依赖于该项目,这是一件好事,并且肯定比让您的丰富域对象依赖于您的 Web 项目更好(如果这甚至是)一个考虑因素 - 我意识到你并没有说你正在这样做)。

如果您的 DTO 是特定于视图的,那么我会将它们包含在您的 UI 项目中。 确保视图只从模型中获取它需要的内容实际上应该是控制器的工作 - 在您的情况下是一个仅包含视图所需字段的值对象。

Are you using actual services (web or WCF)? If so, then define the DTOs in the service layer and the proxy created when you add a service (or web if using old ASMX) reference will contain all of the DTO types. This is the simplest way to do it and maintains only loose coupling between your ASP.NET project and your service project -- no direct project reference is required in either direction. As you update your DTOs, all you need to do is update your service reference and it will automatically expose the updates to your web project via the proxy class that is generated.

In any event, if you're following something like a DDD approach it is best to have your infrastructure projects (such as a web-platform-specific UI) referencing your domain objects than vice versa. If you follow my advice above, however, your web project won't have a direct dependency on the project at all, which is a good thing, and certainly better than having your rich domain objects depending on your web project (if that were even a consideration - I realize you weren't saying you were doing this).

If your DTOs are view-specific, then I would include them in your UI project. It should really be the controller's job to ensure that the View only gets from the Model what it needs - in your case a value-object with just the fields needed by the view.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文