В каком проектном слое должен находиться экран DTO?


У меня есть проект, в котором мы используем экранные 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; }
}   

Edit

Вот еще один пример кода для описания варианта использования где модель домена не задействована. Может быть, это немного прояснит ситуацию. Я полагаю, что перегружаю значение DTO. Я не говорю о DTO для функции передачи объекта по проводу. Я создаю DTOs для формализации контрактов между коммуникациями на уровне моего сервиса.

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())

2 9

2 ответа:

Даже если канонический вариант использования для " DTO "является более" сериализуемым объектом, который может быть передан по проводу", в этом случае вы действительно имеете в виду больше "объектов представления-передачи" или "моделей представления".

Как правило, для наших проектов ответ на вопрос, где они живут, заключается в том, что код "трансляции" сопоставляет модель домена DDD классам PTO. Если это в слое Prensenation (возможно, не такой уж большой ответ), то pres. слой-это место, где я бы объявил ПТО. Но чаще всего это "сервис", который выполняет перевод для вас, и это означает, что и "сервис", и "презентационный" слой нуждаются в ссылках на PTOs, и это (обычно) приводит к их объявлению в отдельном нейтральном проекте/сборке/пространстве имен/что-то, на что могут ссылаться и слой презентации, и слой сервиса.

Используете ли вы реальные сервисы (web или WCF)? Если это так, то определите DTO в слое сервиса, и прокси, созданный при добавлении сервиса (или веб-ссылки, если используется старый ASMX), будет содержать все типы DTO. Это самый простой способ сделать это и поддерживает только свободную связь между вашими ASP.NET проект и ваш сервисный проект - ни в одном из направлений не требуется прямой ссылки на проект. По мере обновления DTOs, все, что вам нужно сделать, это обновить ссылку на сервис, и он будет автоматически предоставлять обновления для вашего веб-проекта через прокси-класс, который создается.

В любом случае, если вы используете что-то вроде DDD-подхода, лучше всего, чтобы ваши инфраструктурные проекты (например, пользовательский интерфейс для веб-платформы) ссылались на ваши доменные объекты, чем наоборот. Однако, если вы последуете моему совету выше, ваш веб-проект не будет иметь прямой зависимости от проекта вообще, что является хорошей вещью и, безусловно, лучше, чем иметь ваши богатые доменные объекты в зависимости от вашего веб - проекта (если бы это было даже соображением-я понимаю, что вы не говорили, что делаете это).

Если ваши DTO зависят от вида, то я бы включил их в ваш проект пользовательского интерфейса. На самом деле это должна быть работа контроллера, чтобы гарантировать, что представление получает от модели только то, что ему нужно - в вашем случае объект value-с только полями, необходимыми для представления.