2016-07-20 16 views
5

Ich möchte AutoFac verwenden, um den aktuellen Prinzipal in die Objekte zu injizieren, die es benötigen. Angenommen, ich habe ein Objekt (AuthorizationValidator), das Sicherheitsprüfungen durchführt. Es sieht etwa so aus:AutoFac: Inject Nullwerte

public AuthorizationValidator : IAuthorizationValidator 
{ 
    public AuthorizationValidator(IDataAccess dataAccess, IPrincipal principal) 
    { 
    // Save injected objects 
    ... 
    } 

    public bool CheckPermission(Guid objectId, Action action) 
    { 
    // Check if we are authorized at all 
    if (this.principal == null) 
     return false; 

    // Check the permission in the database 
    ... 
    } 
} 

Für meine Web-Anwendung die AuthorizationValidator registriert ist, und ich verwenden Sie die folgende Registrierung des Auftraggebers zu injizieren:

builder.Register<IPrincipal>((c, p) => HttpContext.Current?.User); 

Andere Arten von Anwendungen des Auftraggebers Thread oder etwas ähnliches . Alle Objekte, die den Principal benötigen, erhalten den richtigen Principal injected.

Wenn ein Anruf ohne Autorisierung erfolgt, löst AutoFac eine Ausnahme aus, die besagt, dass das Objekt IPrincipal nicht zur Verfügung gestellt werden kann, da die Fabrik null zurückgegeben hat. In diesem Fall ist ein leerer Prinzipal in Ordnung und sollte keine Ausnahme auslösen.

+0

Ich weiß nicht, was in Autofac ist, aber es gibt eine Chance, dass dies funktionieren könnte: 'Builder.Register ((c, p) => (IPrincipal) HttpContext.Current? .User);' –

+0

Allgemein Sprechen, IoC-Frameworks lassen Sie nicht absichtlich null injizieren. Das ist nicht nur eine Autofac-Sache. –

+0

Wäre das [Null-Objekt-Muster] (https://en.wikipedia.org/wiki/Null_Object_pattern) eine Alternative, wie ich in meiner Antwort vorgeschlagen habe? – fknx

Antwort

5

Im Autofac documentation empfehlen sie die Null Object pattern für solche Szenarien zu verwenden. Sie könnten eine NullPrincipal-Klasse erstellen, die von der IPrincipal-Schnittstelle mit einem privaten Konstruktor erbt, der nur ein readonlystatic-Feld freigibt, das die Standardinstanz bereitstellt. Dann können Sie diese Instanz statt null zurück:

builder.Register<IPrincipal>((c, p) => HttpContext.Current?.User ?? NullPrincipal.Default); 

Natürlich würden Sie alle Orte in Ihrem Code aktualisieren müssen, wo Sie überprüft werden, wenn die Hauptnull ist und prüfen, ob es stattdessen auf die NullPrincipal.Default gleich ist.

1

Um dieses Problem zu lösen, ich habe die IPrincipalFactory Schnittstelle geschaffen, die ohne Umweg über Autofac das aktuelle Haupt erhalten:

public AuthorizationValidator : IAuthorizationValidator 
{ 
    public AuthorizationValidator(IDataAccess dataAccess, IPrincipalFactory principalFactory) 
    { 
    // Save injected objects 
    _dataAccess = dataAccess; 
    _principal = principalFactory.GetCurrentPrincipal(); 
    } 

    public bool CheckPermission(Guid objectId, Action action) 
    { 
    // Same as previous example 
    ... 
    } 
} 

public interface IPrincipalFactory 
{ 
    IPrincipal GetCurrentPrincipal(); 
} 

Für die Anwendung ASP.NET ich folgendes Objekt als IPrincipalFactory registrieren würde:

public class IAspNetPrincipalFactory : IPrincipalFactory 
{ 
    public IPrincipal GetCurrentPrincipal() => HttpContext.Current?.User; 
} 

Obwohl das funktioniert, bin ich nicht ganz glücklich mit dieser Lösung.