Разрешение обработчиков с использованием Factory через контейнер IOC

StackOverflow https://stackoverflow.com//questions/25017370

Вопрос

У меня есть задача рефакторить монолитное приложение MVC (1 действие контроллера с более чем 1000 строками) во что-то более управляемое.

Цель программы — парсить коллекции разных типов одну за другой в определенном порядке.

Вот пример предлагаемого «лучшего» решения...

public interface IFruit
{
}

public class Banana : IFruit
{
}

public class Apple : IFruit
{
}

public interface IFruitHandler<in TFruit> where TFruit : IFruit
{
    void Handle(IEnumerable<TFruit> fruit);
}

public class BananaHandler : IFruitHandler<Banana>
{
    public void Handle(IEnumerable<Banana> fruit)
    {
        Console.WriteLine("break apart the bunch of bananas");

        foreach (var banana in fruit)
        {
            Console.WriteLine("Peel the banana");
        }
    }
}

public class AppleHandler : IFruitHandler<Apple>
{
    public void Handle(IEnumerable<Apple> fruit)
    {
        foreach (var apple in fruit)
        {
            Console.WriteLine("Slice the apple");
        }

        Console.WriteLine("Throw the apple cores away");
    }
}

Как видите, у каждого фрукта есть свой обработчик, и реализация каждого обработчика может незначительно отличаться.Некоторые обработчики делают что-то перед работой с коллекцией, другие делают что-то позже, некоторые делают что-то до И после.

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

Это то, что я имел в виду...

public class Mediator : IMediator
{
    private readonly Func<Type, IFruitHandler<IFruit>> handlerFactory;

    public Mediator(Func<Type, IFruitHandler<IFruit>> handlerFactory)
    {
        this.handlerFactory = handlerFactory;
    }

    public void Execute(IEnumerable<IEnumerable<IFruit>> fruitBundles)
    {
        foreach (var bundle in fruitBundles)
        {
            if (!bundle.Any())
                continue;

            var handler = handlerFactory(bundle.First().GetType());
            handler.Handle(bundle);
        }
    }
}

Набор фруктов всегда будет содержать только один фрукт, а наборы будут располагаться в определенном порядке.Подпись для Mediator.Execute достаточно свободна, чтобы один пакет мог содержать разные плоды.Этого не должно произойти.

Вопрос двоякий....

Я могу зарегистрировать все FruitHandlers с помощью OpenGenerics...

container.RegisterManyForOpenGeneric(typeof(IFruitHandler<>),typeof(IFruitHandler<>).Assembly);

но у меня возникли трудности с правильной регистрацией фабрики. Как мне зарегистрировать фабрику с помощью Simple Injector?

Реализация фабрики медиатора/обработчика кажется неудобной, как и интерфейс IFruit (по сути, это всего лишь маркер) — вы бы изменили дизайн?

Это было полезно?

Решение

Вы можете реализовать Mediator следующим образом, но у него есть некоторые недостатки:

  • оно использует dynamic
  • тот Mediator необходимо ссылаться на Container (хотя это нормально, если вы определите этот класс в корне композиции)

Я считаю, что вопрос слишком общий, чтобы можно было дать какой-либо конкретный совет о том, как лучше разработать решение.

class Mediator : IMediator
{
    private readonly Container container;

    public Mediator(Container container)
    {
        this.container = container;
    }

    public void Handle(IEnumerable<IEnumerable<IFruit>> fruitBundles)
    {
        foreach (var bundle in fruitBundles)
        {
            if (bundle.Any())
            {
                dynamic instance = bundle.First();
                this.Handle(instance, bundle);
            }
        }
    }

    private void Handle<T>(T instance, IEnumerable<IFruit> bundle)
        where T : IFruit
    {
        var handler = this.container.GetInstance<IFruitHandler<T>>();

        handler.Handle(bundle.Cast<T>());
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top