Reputation: 6531
I have a class which needs to set an IPrinciple
object on construction, based on the current authenticated user.
I found some other code which I tried but it didn't work:
private readonly Lazy<IPrincipal> _principal;
public MyService(Lazy<IPrincipal> principal)
{
_principal = principal;
}
And I configured Simple Injector like so:
container.Register(() => new Lazy<IPrincipal>(() => HttpContext.Current.User));
Apparently _principal
is undefined/not set to an instance of an object when I try running this.
I also tried:
container.Register(() => new Lazy<IPrincipal>(() => Thread.CurrentPrincipal));
This allowed me to check _principal.Value.Identity.IsAuthenticated
but was always returning false
.
Upvotes: 5
Views: 1233
Reputation: 172606
The root of your problems is caused by the fact that you inject runtime data into your components during object graph construction. As explained here, this is a bad idea.
Instead, as the referenced article advices, you should delay the decision of requesting this runtime data until after the graph is built; at the time that this runtime data is available.
You can do this by creating a custom IPrincipal
implementation like this:
public class HttpContextPrinciple : IPrincipal
{
public IIdentity Identity => HttpContext.Current.User.Identity;
public bool IsInRole(string role) => HttpContext.Current.User.IsInRole(role);
}
And register it like this:
container.RegisterSingleton<IPrincipal>(new HttpContextPrinciple());
This allows you to inject IPrincipal
directly into consumers like MyService
. This simplifies the consumers, since they don't have to deal with leaky abstractions such as Lazy<T>
.
Upvotes: 8