3

実装は OWIN コンテキストからIAuthenticationManager取得できますが、Castle Windsor のコンポーネント登録はコンポーネントを解決する前に行う必要があるため、どこにでも注入されるようにコンポーネントとして登録するにはどうすればよいですか?IAuthenticationManager

私の知る限り、私は を使用する必要がありますComponent.For<IAuthenticationManager>().UsingFactoryMethod(...)が、OWIN/Katana を使用しているため、次のようなものHttpContext.Current.GetOwinContext()は機能しません (機能する場合はこのために依存関係を追加したくありませんSystem.Web...)。

現時点での解決策は何ですか?

4

2 に答える 2

2

一時的な(または決定的な)解決策...

これが私が問題を解決することができた方法です。

まず、単純な OWIN ミドルウェアを実装しました。

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

IAuthenticationManagerを使用して構成しComponentRegistration<T>.UseFactoryMethodたので、次のような拡張メソッドを実装しました。

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

最後に、私はIAuthenticationManagerこの方法で登録しました:

Component.For<IAuthenticationManager>().UseOwinComponentFactoryMethod().LifestyleTransient()

臭い...

ところで、このソリューションの信頼性については自信がありません。これは、リクエストしたスレッドとは別のスレッドでコンポーネントを解決しようとしない限り機能するはずだからです。

悲しいことに、このソリューションが失敗する可能性があるのは多くの状況です。あなたのコードが非ブロッキング I/O を実装している場合、IAuthenticationManager"owinContext" を設定したスレッドから別のスレッドへの注入を試みることを期待していCallContextます...

より良い、よりエレガントな解決策を見つけている間、私はまだ他の答えを楽しみにしています.

于 2015-08-05T09:59:34.513 に答える
0

への依存関係を気にしない人のためSystem.Webに、次のコードが機能するはずです (ミドルウェアは必要ありません)。

private static IAuthenticationManager GetAuthenticationManager(IKernel kernel, ComponentModel componentModel, CreationContext creationContext)
{
    var owinContext = new HttpContextWrapper(HttpContext.Current).GetOwinContext();

    return owinContext.Authentication;
}

次に、城のウィンザーインストーラーで:

container.Register(Component.For<IAuthenticationManager>()
                            .UsingFactoryMethod(GetAuthenticationManager, managedExternally: true)
                            .LifestyleTransient())
于 2016-11-19T13:01:10.800 に答える