Frage

Ich habe die Aufgabe, eine monolithische MVC-Anwendung (1 Controller-Aktion mit über 1000 Zeilen) in etwas besser Handhabbares umzugestalten.

Der Zweck des Programms besteht darin, Sammlungen verschiedener Typen nacheinander in einer bestimmten Reihenfolge zu analysieren.

Hier ist ein Beispiel für eine vorgeschlagene 'bessere' Lösung...

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");
    }
}

Wie Sie sehen, hat jede Frucht ihren eigenen Handler, und jede Handler-Implementierung kann sich geringfügig unterscheiden.Einige Handler erledigen Dinge, bevor sie die Sammlung durcharbeiten, andere erledigen Dinge danach, andere machen Dinge vorher UND nachher.

Die Anwendung präsentiert ein Objekt (über einen MVC-Controller) mit all den verschiedenen Fruchtsammlungen als Eigenschaften (im Grunde ein großes Ansichtsmodell).Ich hätte gerne eine Art Mediator, der all diese Sammlungen aufnehmen und an den entsprechenden Handler weitergeben kann.

Das hatte ich mir vorgestellt...

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);
        }
    }
}

Ein Fruchtbündel enthält immer nur eine Frucht, und die Bündel sind in einer bestimmten Reihenfolge angeordnet.Die Unterschrift für den Mediator.Execute ist locker genug, damit ein Bündel verschiedene Früchte enthalten kann.Das sollte nicht passieren.

Die Frage ist zweifach....

Ich kann alle fruithandler bei OpenGenerics registrieren...

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

aber ich habe Schwierigkeiten, die Registrierung für das Werk korrekt zu machen - wie registriere ich das Werk bei Simple Injector?

Die Implementierung der Mediator / Handler-Factory fühlt sich umständlich an, ebenso wie die iFruit-Schnittstelle (die effektiv nur ein Marker ist) - würden Sie das Design ändern?

War es hilfreich?

Lösung

Sie können das implementieren Mediator auf folgende Weise hat es aber einige Nachteile:

  • es verwendet dynamic
  • der Mediator muss auf das verweisen Container (obwohl dies in Ordnung ist, wenn Sie diese Klasse in Ihrem Kompositionsstamm definieren.)

Ich halte die Frage für zu allgemein, um konkrete Ratschläge zu einer besseren Gestaltung Ihrer Lösung geben zu können.

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>());
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top