Как получить объект домена из репозитория
У меня есть небольшая проблема с пониманием отношения объекта репозитория к домену. Вот некоторая информация, которую я знаю о дизайне домена (они также могут быть неверными или неточными). И с учетом этого я не могу найти способ получить объект домена из хранилища.
В DDD домен должен знать и содержать только то, что нужно для бизнеса, а все остальное должно быть удалено из домена. Все в порядке. А также абстракция доступа к данным из любого бизнеса также является хорошей практикой. Приложению не нужно знать, где мы храним данные или как мы храним данные. Мы только просим репозиторий дать нам объект домена, и он дает нам объект, который мы хотим, или другой способ также допустим, мы даем хранилищу объект домена, и он отправляет его в хранилище.
Объявление открытых сеттеров для доменных объектов также является очень плохим подходом в объектно-ориентированном проектировании, поскольку мы не сможем контролировать, кто что получает и что меняет. Так что это хорошая практика, чтобы выставлять только то, что нужно для вне объекта.
Поэтому, помня об этом, я не могу найти способ реализовать свои репозитории. Я могу использовать любой ORM или чистый SQL в моем коде и получать данные.
Но я не могу создавать доменные объекты из персистентных объектов;
- Поскольку они не имеют общедоступных сеттеров, я не могу создавать и устанавливать значения полей.
- Объявление открытых конструкторов, содержащих все поля, кажется неправильным. У меня может быть несколько моделей для заполнения, это означает, что мне нужно определить несколько конструкторов с разными наборами параметров.
Любая помощь будет оценена...
3 ответа
Есть варианты у вас есть:
1. ORM могут работать с приватными полями.
Как я знаю, ORM (например, Entity Framework, NHibernate) могут устанавливать свойства через непубличные установщики.
Есть пример, который доказывает это для Entity Framework - Entity Framework, Private Constructors и Private Setters.
Если вы используете NHibernate, ваши сеттеры должны быть public/protected virtual
/ protected internal virtual
или же private
поле поддержки может быть использовано. Вы можете найти больше информации в Стратегиях доступа к собственности в вопросе NHibernate SO.
2. Отражение может быть использовано.
Он также может быть использован для получения доступа к частным полям / свойствам. Можно установить частную собственность через отражение.
3. Неплохая практика иметь публичный конструктор для создания вашей сущности.
Объявление открытых конструкторов, содержащих все поля, кажется неправильным. У меня может быть несколько моделей для заполнения, это означает, что мне нужно определить несколько конструкторов с разными наборами параметров.
Вашим доменным объектам нужен только один публичный конструктор с полным списком свойств, которые они имеют. Достаточно иметь только один конструктор, несмотря на наличие нескольких моделей для заполнения. Репозитарий отвечает за корректный вызов конструктора и сопоставление модели с ее параметрами.
Редактировать:
4. Automapper может быть использован.
Следующий тест показывает, что AutoMapper может отображать свойства через частные установщики.
[TestClass]
public class AutomapperTest
{
[TestMethod]
public void Test()
{
// arrange
Mapper.CreateMap<AModel, A>();
var model = new AModel { Value = 100 };
//act
var entity = Mapper.Map<A>(model);
// assert
entity.Value.Should().Be(100);
entity.Value.Should().Be(model.Value);
}
}
public class AModel
{
public int Value { get; set; }
}
public class A
{
public int Value { get; private set; }
}
Это не правда, что вы не можете создавать доменные объекты с ORM без публичных сеттеров. Если вы используете Entity Framework, он определенно может отображать частные свойства в подходе сначала модели, и вам нужны только публичные методы получения в подходе кода сначала. Я не знаю, как насчет других ORM-ов.
Я пытаюсь понять ваш запрос здесь. Несколько советов о том, как вы можете продолжить. Прежде всего, Домен должен знать контракты репозитория, а не фактическую инфраструктуру репозитория. другими словами, вы можете выбрать 3 класса библиотеки следующим образом
- XYZDomain (узнает XYZRepository и вызовет соответствующие методы этого интерфейса)
- XYZRepository (содержит интерфейс интерфейса IXYZService)
- XYZSQLRepository (актуальная реализация интерфейсов XYZRepository).
Теперь вам нужно выбрать, куда внедрить XYZSQLRepository в XYZDomain, используя внедрение зависимостей.
Вы также можете попробовать использовать модель событий для регистрации этих репозиториев, если хотите.
Используйте пользовательский Сервисный Локатор, чтобы получить конкретные объекты