В каком проектном слое должен находиться экран 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 ответа:
Даже если канонический вариант использования для " DTO "является более" сериализуемым объектом, который может быть передан по проводу", в этом случае вы действительно имеете в виду больше "объектов представления-передачи" или "моделей представления".
Как правило, для наших проектов ответ на вопрос, где они живут, заключается в том, что код "трансляции" сопоставляет модель домена DDD классам PTO. Если это в слое Prensenation (возможно, не такой уж большой ответ), то pres. слой-это место, где я бы объявил ПТО. Но чаще всего это "сервис", который выполняет перевод для вас, и это означает, что и "сервис", и "презентационный" слой нуждаются в ссылках на PTOs, и это (обычно) приводит к их объявлению в отдельном нейтральном проекте/сборке/пространстве имен/что-то, на что могут ссылаться и слой презентации, и слой сервиса.
Используете ли вы реальные сервисы (web или WCF)? Если это так, то определите DTO в слое сервиса, и прокси, созданный при добавлении сервиса (или веб-ссылки, если используется старый ASMX), будет содержать все типы DTO. Это самый простой способ сделать это и поддерживает только свободную связь между вашими ASP.NET проект и ваш сервисный проект - ни в одном из направлений не требуется прямой ссылки на проект. По мере обновления DTOs, все, что вам нужно сделать, это обновить ссылку на сервис, и он будет автоматически предоставлять обновления для вашего веб-проекта через прокси-класс, который создается.
В любом случае, если вы используете что-то вроде DDD-подхода, лучше всего, чтобы ваши инфраструктурные проекты (например, пользовательский интерфейс для веб-платформы) ссылались на ваши доменные объекты, чем наоборот. Однако, если вы последуете моему совету выше, ваш веб-проект не будет иметь прямой зависимости от проекта вообще, что является хорошей вещью и, безусловно, лучше, чем иметь ваши богатые доменные объекты в зависимости от вашего веб - проекта (если бы это было даже соображением-я понимаю, что вы не говорили, что делаете это).
Если ваши DTO зависят от вида, то я бы включил их в ваш проект пользовательского интерфейса. На самом деле это должна быть работа контроллера, чтобы гарантировать, что представление получает от модели только то, что ему нужно - в вашем случае объект value-с только полями, необходимыми для представления.