Как получить объект домена из репозитория

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

В DDD домен должен знать и содержать только то, что нужно для бизнеса, а все остальное должно быть удалено из домена. Все в порядке. А также абстракция доступа к данным из любого бизнеса также является хорошей практикой. Приложению не нужно знать, где мы храним данные или как мы храним данные. Мы только просим репозиторий дать нам объект домена, и он дает нам объект, который мы хотим, или другой способ также допустим, мы даем хранилищу объект домена, и он отправляет его в хранилище.

Объявление открытых сеттеров для доменных объектов также является очень плохим подходом в объектно-ориентированном проектировании, поскольку мы не сможем контролировать, кто что получает и что меняет. Так что это хорошая практика, чтобы выставлять только то, что нужно для вне объекта.

Поэтому, помня об этом, я не могу найти способ реализовать свои репозитории. Я могу использовать любой ORM или чистый SQL в моем коде и получать данные.

Но я не могу создавать доменные объекты из персистентных объектов;

  1. Поскольку они не имеют общедоступных сеттеров, я не могу создавать и устанавливать значения полей.
  2. Объявление открытых конструкторов, содержащих все поля, кажется неправильным. У меня может быть несколько моделей для заполнения, это означает, что мне нужно определить несколько конструкторов с разными наборами параметров.

Любая помощь будет оценена...

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 класса библиотеки следующим образом

  1. XYZDomain (узнает XYZRepository и вызовет соответствующие методы этого интерфейса)
  2. XYZRepository (содержит интерфейс интерфейса IXYZService)
  3. XYZSQLRepository (актуальная реализация интерфейсов XYZRepository).

Теперь вам нужно выбрать, куда внедрить XYZSQLRepository в XYZDomain, используя внедрение зависимостей.

Вы также можете попробовать использовать модель событий для регистрации этих репозиториев, если хотите.

Используйте пользовательский Сервисный Локатор, чтобы получить конкретные объекты

Другие вопросы по тегам