2015-05-22 9 views
9

Ich habe die folgende Extension-Methode, die (natürlich) in einer statischen Klasse existiert.Wie löst man die Abhängigkeit in der statischen Klasse mit Unity?

public static class MyExtensions 
{ 
    [Dependency] 
    private static IMyDataContext _myDataContext { get; set; } 

    public static void MyExtensionMethod(this MyType myType) 
    { 
     // do stuff 

     _myDataContext.DoAwesomeThing(); 
    } 
} 

das _myDataContext Objekt ist null.

Normalerweise würde ich die UnityContainer verwenden, um den Typ zu registrieren, aber da dies eine statische Klasse ist, kann ich nicht.

Was muss ich instanziieren _ myDataContext, damit es nicht null ist, wenn ich es brauche?

Antwort

12

Wie Sie bereits erwähnt haben, kann Unity nicht zum Auflösen der Klasse verwendet werden, da sie statisch ist. Dafür gibt es ein paar Optionen. Mein persönlicher Favorit ist das Abstract Factory-Muster. Ich tendiere dazu, das Muster zu optimieren, um mit DI gut zu funktionieren.

Die Fabrik der Regel sieht irgendwie wie folgt aus:

/// <summary> 
/// Creates an IMyDataContext instance 
/// </summary> 
public static class MyDataContextFactory 
{ 
    /// <summary> 
    /// The factory used to create an instance 
    /// </summary> 
    static Func<IMyDataContext> factory; 

    /// <summary> 
    /// Initializes the specified creation factory. 
    /// </summary> 
    /// <param name="creationFactory">The creation factory.</param> 
    public static void SetFactory(Func<IMyDataContext> creationFactory) 
    { 
     factory = creationFactory; 
    } 

    /// <summary> 
    /// Creates a new IMyDataContext instance. 
    /// </summary> 
    /// <returns>Returns an instance of an IMyDataContext </returns> 
    public static IMyDataContext CreateContext() 
    { 
     if (factory == null) throw new InvalidOperationException("You can not create a context without first building the factory."); 

     return factory(); 
    } 
} 

In der Bootstrap-Prozess (wo immer Sie Ihren Service-Registrierungen Setup) können Sie die Fabrik initialisieren können Ihre Abhängigkeit zu lösen.

MyDataContextFactory.SetFactory(() => this.Container.Resolve<IMyDataContext>()); 

Jetzt in Ihrer Erweiterungsmethode, holen Sie einen Kontext.

public static class MyExtensions 
{ 
    public static void MyExtensionMethod(this MyType myType) 
    { 
     MyDataContextFactory.CreateContext().DoAwesomeThing(); 
    } 
} 

Ihre Unity Registrierung des Kontextes, können die verschiedenen unterschiedlichen Konfigurationen des Dienstes behandeln, wenn es Bedingungen gibt es zu lösen. Wenn die Möglichkeit besteht, dass der Kontext durch etwas anderes als Unity festgelegt werden kann, kann dieser Besitzer einfach einen neuen Delegaten übergeben, den die Erweiterungsmethode verwendet.

Ich vermeide es, die Container selbst in meine Fabriken zu geben, da dies zu einer engen Kopplung der Container an meine App führt. Wenn ich etwas an die Fabrik übergebe, würde ich lieber ein Fabrikdelegierter sein, der über DI auflösen würde, als den DI-Container selbst zu übergeben.

+0

Wie kann ich die obige Implementierung generisch machen? Wie möchte ich irgendeine Schnittstelle weitergeben? IMyDataContext kann eine beliebige Schnittstelle sein. Können Sie eine Implementierung bereitstellen? –

+0

Sie würden einfach die Methoden 'SetContext' und' CreateContext' generisch machen. Ihre Implementierung würde '' anstelle von 'IDataContext' auflösen. Sie müssten den 'Func ' speichern und dann versuchen, ihn auf 'Func 'zu' 'werfen, wenn Sie' CreateContext' aufrufen. Ehrlich gesagt würde ich jedoch eine Erweiterungsmethode verwenden, die Daten aus einer statischen Klasse wie dieser zurückgeben muss. Stellen Sie die Abhängigkeiten in Ihren Aufruferkonstruktor ein und stellen Sie dann die Abhängigkeit in Ihrem Erweiterungsmethodenaufruf als Methodenparameter bereit. –