2016-07-13 28 views
1

Ist es möglich, mithilfe einer benutzerdefinierten Factory-Methode den übergeordneten Typ des Auflösungstyps in Unity zu ermitteln. Ich versuche, einen Logger zu erstellen, der bereits einen Kontext für das übergeordnete Objekt hat.Erstellen eines Objekts aus benutzerdefinierter InjectionFactory in Unity

// ... other types being registered 
container.RegisterType<ILogger>(new InjectionFactory(ResolveLogger)); 

// Custom factory method 
private ILogger ResolveLogger(IUnityContainer container) 
{ 
    // I want to know the type of the parent that requires the ILogger interface so that I can add it to my logging context (with Serilog): 
    Type parentType = ??? 
    return Log.Logger.ForContext(parentType); 
} 

Wenn ich eine Instanz einer Klasse zu erstellen, ermöglicht Serilog mich auf diese Weise einen Kontext für den Logger zu setzen:

public class MyService 
{ 
    private readonly ILogger logger; 
    public MyService(ILogger logger) 
    { 
     this.logger = logger.ForContext(this.GetType()); 
    } 
} 

Danach werden alle Anrufe zu this.logger.Information("Hello World") werden zusätzliche Metadaten Der Aufruf wurde in der MyService-Klasse ausgeführt.

Ich versuchte zu vermeiden zu müssen, logger.ForContext(this.GetType()) in jeder Klasse, die einen Logger verbraucht, zu rufen, indem Unity die Arbeit für mich erledigen lässt.

+1

Könnten Sie versuchen zu erklären, was Sie Ziel Ziel ist. Vielleicht gibt es eine bessere Lösung. – Michael

+0

Ich habe die Frage mit meinem spezifischen Ziel aktualisiert. –

+0

Nicht sicher, dass Unity diese Informationen bereitstellt. Sie könnten versuchen, einige benutzerdefinierte Resolver oder benutzerdefinierte Richtlinien oder benutzerdefinierte Buildup zu untersuchen. Aber ich denke Log4Net macht was du willst .. – Michael

Antwort

1

Ich glaube nicht einmal eine benutzerdefinierte Politik würde Sie bekommen, was Sie wollen. Ich bin mir nicht sicher, ob es sogar einen Haken gibt, der Ihnen den "Eltern" -Typ anzeigt. Ich könnte falsch liegen. Aber hier ist eine alternative Lösung und was ich benutze.

Sie könnten Generics verwenden, um den aufrufenden Typ zu erhalten (ähnlich wie ForContext Sie erwähnt, aber ein wenig eleganter). Und Sie könnten [CallerMemberName] verwenden, um den Namen des aufrufenden Mitglieds (Methodenname, Eigenschaftenname usw.) abzurufen.


So ...

public interface ILogger<T> 
{ 
    void Write(string message, [CallerMemberName] string callingMethod = ""); 
} 

und die Einheit Registrierung offen Generika so ...

container.RegisterType(typeof(ILogger<>), typeof(ConsoleLogger<>)); 

Und hier ist ein Beispiel unter Verwendung würde Verwendung ...

public class MyService 
{ 
    public MyService(ILogger<MyFileService> logger) 
    { 
     // Check for nulls, set to member variable, etc. 
    } 
} 

Aber beachten Sie, dass dies nicht mit statischen Typen funktioniert als statische Typen nicht als generische Argumente verwendet werden können (dies ist nicht wirklich ein Problem für mich, weil ich versuche, statische Typen zu vermeiden).

Ich habe ein Beispiel here verspottet.