Как я могу использовать поле Type Discriminator в моем DTO для создания экземпляра соответствующего объекта домена с DI? - PullRequest
1 голос
/ 11 февраля 2010

Я ищу предложения о том, как сопоставить один класс DTO с дискриминатором типов для нескольких классов домена.

У меня есть мой DTO:

public class FooData
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string TypeDiscrim { get; set; }
}

public class FooDataRepository
{
    public List<FooData> GetAll() { /* select * from foo, basically */ }
}

У меня есть объект базового домена с зависимостью конструктора от хранилища с универсальным параметром:

public interface IFooDomain {}

public class FooDomainBase<B1> : IFooDomain where B1 : BarBase
{
    protected IBarRepository<B1> _barRepository;

    public FooDomainBase(FooData data, IBarRepository<B1> barRepository)
    {
        Id = data.Id;
        Name = data.Name;
        _barRepository = barRepository;
    }

    public virtual void Behavior1()
    {
        B1 thingToDoStuffWith = _barRepository.GetBar();
        /* do stuff */
    }

    public Guid Id { get; set; }
    public string Name { get; set; }
}

public class BarBase {}    

public interface IBarRepository<B1> where B1 : BarBase
{
    B1 GetBar();
}

Тогда у меня есть образец наследника от моего объекта базового домена:

// There will be several of these
public class SuperFooDomain1 : FooDomainBase<SuperBar>
{
    public SuperFooDomain1(FooData data, IBarRepository<SuperBar> barRepository) : base(data, barRepository)
    { }

    public override void  Behavior1() { /* do something different than FooDomainBase */ }
}

public class SuperBar : BarBase { }

Теперь вот кикер: у меня есть класс, который будет использовать список IFooDomain, который он получает из репозитория. (IFooDomain необходим из-за параметра типа в FooDomainBase.)

// The FooManager class (not pictured) will use this to get all the 
public class FooRepository
{
    private FooDataRepository _datarepository;

    public FooRepository(FooDataRepository dataRepository)
    {
        _datarepository = dataRepository;
    }

    public List<IFooDomain> GetAll()
    {
        foreach (var data in _datarepository.GetAll())
        {
            // Convert FooData into appropriate FooDomainBase inheritor
            // depending on value of FooData.TypeDiscrim
        }
    }

}

Могу ли я получить поведение в комментариях выше с помощью DI Framework? Я предполагаю, что мне нужно в качестве шаблона Service Locator вернуть мне экземплярный экземпляр FooDomainBase, но мне также нужен разрешенный параметр конструктора IBarRepository<SuperBar>.

Какие фреймворки могут обрабатывать подобные вещи? Если не из коробки, что мне нужно продлить?

Я также открыт для критики иерархии объектов, так как это может указывать на недостаток в дизайне выше.

1 Ответ

1 голос
/ 11 февраля 2010

Я не уверен, что смог следить за всеми вещами Foo / Bar, но стандартное решение такого рода проблемы заключается в введении одного или нескольких абстрактных фабрик в рассматриваемого потребителя.

Определение:

public interface IFooDomainFactory
{
    IFooDomain Create(string discriminator);
}

и вставьте его в FooRepository. Когда вы реализуете IFooDomainFactory, вам понадобится способ получить IBarRepository<SuperBar>, но теперь вы можете определить новую абстрактную фабрику, которая дает вам это, и внедрить ее в конкретный FooDomainFactory.

Вам не нужен какой-либо конкретный DI-контейнер для этого, но все они способны разрешать подобные зависимости.

Не использовать Service Locator - это анти-шаблон .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...