Since IAuthenticationManager
implementation can be retrieved from OWIN context, but Castle Windsor's component registration must be done before resolving components, how can I register IAuthenticationManager
as component to get injected anywhere?
AFAIK, I should use Component.For<IAuthenticationManager>().UsingFactoryMethod(...)
, but since I'm using OWIN/Katana, something like HttpContext.Current.GetOwinContext()
won't work (and if it would work, I would hate to add a dependency to System.Web
for this...).
What's the solution for this right now?
This is how I've managed to solve the issue.
First of all, I've implemented a simple OWIN middleware:
public sealed class WindsorMiddleware : OwinMiddleware
{
public WindsorMiddleware(OwinMiddleware next) : base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
CallContext.LogicalSetData("owinContext", context);
await Next.Invoke(context);
CallContext.FreeNamedDataSlot("owinContext");
}
}
And I've configured IAuthenticationManager
using ComponentRegistration<T>.UseFactoryMethod
so I've implemented an extension method like this:
public static ComponentRegistration<TService> UseOwinComponentFactoryMethod<TService>(this ComponentRegistration<TService> registration)
where TService : class
{
return registration.UsingFactoryMethod
(
(kernel, componentModel, creationContext) =>
{
IOwinContext owinContext = CallContext.LogicalGetData("owinContext") as IOwinContext;
Contract.Assert(owinContext != null);
if (creationContext.RequestedType == typeof(IAuthenticationManager))
{
return (TService)owinContext.Authentication;
}
else
{
throw new NotSupportedException();
}
},
managedExternally: true
);
}
Finally, I've registered IAuthenticationManager
this way:
Component.For<IAuthenticationManager>().UseOwinComponentFactoryMethod().LifestyleTransient()
BTW, I'm not self-convinced about the reliability of this solution since this should work unless you try to resolve components in another thread than the request one.
Sadly, it should be a lot of situations where this solution can fail. If your code implements non-blocking I/O, I expect to try to inject IAuthenticationManager
from another thread from the one that set "owinContext" in the CallContext
...
I'll still look forward for other answers while I find a better and more elegant solution.