2016-07-20 35 views
5

Chcę użyć AutoFac do wstrzyknięcia aktualnej wartości głównej w obiektach, które jej potrzebują. Załóżmy, że mam obiekt (AuthorizationValidator), który wykonuje kontrole bezpieczeństwa. Wygląda to mniej więcej tak:AutoFac: Wprowadzanie wartości NULL

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 
    ... 
    } 
} 

Dla mojej aplikacji internetowej AuthorizationValidator jest zarejestrowany i używam następujący rejestrację aby wstrzyknąć Zleceniodawca:

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

Inny rodzaj aplikacje używają głównego wątku lub coś podobnego . Wszystkie obiekty wymagające zleceniodawcy otrzymują odpowiednią moc główną, którą wstrzyknięto.

Jeśli wywołanie zostanie wykonane bez autoryzacji, to AutoFac zgłosi wyjątek informujący mnie, że nie może dostarczyć obiektu IPrincipal, ponieważ fabryka zwróciła null. W takim przypadku pusty zleceniodawca jest w porządku i nie powinien zgłaszać wyjątku.

+0

Nie wiem, co jest w Autofac, ale jest szansa, że ​​to zadziała: 'builder.Register ((c, p) => (IPrincipal) HttpContext.Current? .User);' –

+0

Ogólnie mówiąc, framework IoC nie pozwoli ci celowo wstrzykiwać nu. To nie jest tylko sprawa Autofac. –

+0

Czy [wzór obiektu zerowego] (https://en.wikipedia.org/wiki/Null_Object_pattern) byłby alternatywą, jak zasugerowałem w mojej odpowiedzi? – fknx

Odpowiedz

5

W przypadku Autofac documentation zaleca się stosowanie do takich scenariuszy wartości Null Object pattern. Można utworzyć klasę NullPrincipal dziedziczącą po interfejsie IPrincipal z prywatnym konstruktorem, który eksponuje tylko pole readonlystatic, które zapewnia domyślną instancję. Następnie można powrócić to wystąpienie zamiast null:

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

Oczywiście trzeba by zaktualizować wszystkie miejsca w kodzie, w którym sprawdzamy, czy zleceniodawca jest nieważna i sprawdzić, czy jest równa NullPrincipal.Default zamiast.

1

Aby rozwiązać ten problem, stworzyliśmy interfejs IPrincipalFactory które można otrzymać aktualny kapitał bez przechodzenia przez AutoFac:

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

Dla aplikacji ASP.NET chciałbym zarejestrować następujący obiekt jako IPrincipalFactory:

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

Chociaż to działa, nie jestem w pełni zadowolony z tego rozwiązania.