Frage

Ich habe durch die Details der Implementierung von IOC in meinen Web -Apps gearbeitet, aber auf eine Weise, die Microsoft.Practices.Servicelocation nutzt. Ich verwende speziell AutoFAC und die ASP.NET -Integration, aber ich wollte mich für andere Container offen lassen. In den Bereichen von diese Frage, Ich war besorgt darüber, wie ich in meinem Web -App -Code auf den Container zugreifen soll.

Ich habe eine "Kern" -Bibliothek, die hauptsächlich Schnittstellen definiert, die gelöst werden sollen. Diese Kernbibliothek wird auch von meiner Web -App und anderen Apps verwendet. Sehr praktisch, um gemeinsame Schnittstellen zu definieren. Ich dachte, dies wäre ein ausgezeichneter Ort, um Zugang zum IOC -Behälter zu verleihen, und ich tat dies mit einem statischen Unterricht. Der Trick injiziert den Behälter in die statische Klasse.

In einer Webumgebung ist es schwierig, weil der Container für jede Anfrage unterschiedlich sein kann, während es in einer Nicht-Web-App wahrscheinlich ständig gleich sein wird. Zuerst habe ich versucht, die Container -Direclty mit einer Methode zu injizieren, aber das fehlgeschlagen in der nächsten Webanforderung schnell! Also habe ich mir das ausgedacht:

public static class IoCContainer
{
    public static void SetServiceLocator(Func<IServiceLocator> getLocator)
    {
        m_GetLocator = getLocator;
    }
    static private Func<IServiceLocator> m_GetLocator = null;

    public static T GetInstance<T>(string typeName)
    {
        return m_GetLocator().GetInstance<T>(typeName);
    }
}

Jetzt in meinem global.asax.cs mache ich das:

protected void Application_Start(object sender, EventArgs e)
{
    var builder = new Autofac.Builder.ContainerBuilder();
    ... register stuff ...
    var container = builder.Build();
    _containerProvider = new Autofac.Integration.Web.ContainerProvider(container);
    Xyz.Core.IoCContainer.SetServiceLocator(() => 
        new AutofacContrib.CommonServiceLocator.AutofacServiceLocator
            (_containerProvider.RequestContainer));
}
public IContainerProvider ContainerProvider
{
    get { return _containerProvider; }
}
static IContainerProvider _containerProvider;

Und Anrufe zur Lösung von Abhängigkeiten sehen aus wie

var someService = Xyz.Core.GetInstance<ISomeService>();

Anstatt einen bestimmten Behälter zu übergeben, bestehe ich einen Delegierten, der weiß, wie man einen Container bekommt. Für Nicht-Web-Anwendungen würde der Delegierte wahrscheinlich nur das zurückgeben, was Builder.build () dient.

Meine Frage an die Experten ist, macht das Sinn? Ich habe eine einfache Möglichkeit, etwas zu erreichen, das Abhängigkeiten lösen kann, ohne zu wissen, was das Containerprodukt ist oder woher der Container selbst stammt. Was denkst du?

War es hilfreich?

Lösung

Wir verwenden ein ähnliches Muster hauptsächlich aufgrund der Tatsache, dass IOC in eine Nicht-DI-Architektur eingeführt wurde. Die Notwendigkeit, den Container explizit aufzurufen, um Dienste zu erhalten, was im Grunde das Werksmuster ist.

Der wahre Vorteil von IOC wird erzielt, wenn alle Abhängigkeiten injiziert werden können und Ihr Code keine Abhängigkeit vom Service -Locator mehr hat. Autofac.Integration.Web hat Handler, die Injektionen in Ihre Seitenobjekte durchführen, wodurch der statische Service -Locator veraltet wird. IMO Dies ist jedoch die bevorzugte Art und Weise (wie auch in unserem Fall) der Service -Locator kann nicht immer vermieden werden.

Da Sie Ihre App bereits mit der Ioccontainer -Klasse aus dem Container isoliert haben, sehe ich keinen Grund, die zusätzliche Abstraktion des AutofacServicelocator innerhalb von Ioccontainer zu haben. Fazit ist, dass Ioccontainer bereits Ihr Service -Locator ist und direkter Zugriff auf die Containerimplementierung "zulässig" sein sollte.

Hier ist meine Einstellung zu Ihrer Service -Locator -Klasse:

public static class IoCContainer
{
    private static IContext GetContainer()
    {
        var cpa = 
             (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
        return cpa.ContainerProvider.RequestContainer;
    }

    public static T GetInstance<T>()
    {
        return GetContainer().Resolve<T>();
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top