2

Ninject.Extensions.Interception3.0.0.8 がクラスの動的プロキシを構築する方法を理解しようとしています。から継承する属性で具象クラスを装飾するInterceptAttributeか、メソッドでバインド時に直接インターセプトするとIntercept()、Ninject は通常の型ではなく、装飾されたクラスの動的プロキシを返すことがわかりました。

例外ロガーインターセプターを追加する具象型にIPolicySearchPresenterバインドするインターフェイスがあります。FlexPolicySearchPresenter

Bind<IExceptionInterceptor>().To<ExceptionInterceptor>();
Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>();

問題は、そのバインディングの戻り値の型を検査すると、次のようになることです。

var proxy = Kernel.Get<IPolicySearchPresenter>();

Castle.Proxies.IPolicySearchPresenterProxy代わりにのインスタンスを取得しますFlexPolicySearchPresenterProxy

これにより、私の FluorineFx リモート処理アプリで問題が発生しています。ただし、キャッスル プロキシを手動で作成すると、次のようになります。

ProxyGenerator generator = new ProxyGenerator();
    //My presenter type
    Type type = typeof(FlexPolicySearchPresenter);
    //My presenter interface
    var interfaceType = type.GetInterfaces().Single();
    //Get my Interceptor from container. Notice that i had to 
    //change my Interceptor to implement IInterceptor from Castle libs,
    // instead of Ninject IInterceptor
    var excepInt = Kernel.Get<ExceptionInterceptor>();
    //Manually get all my instances required by my presenter type Constructor
    //ideally passed through Constructor Injection
    var presenterSearchService = Kernel.Get<IPolicySearchService>();
    var userAuthService = Kernel.Get<IUserAuthorizationService>();
    //Create proxy, passing interceptor(s) and constructor arguments
    var proxy = generator.CreateClassProxy(type, new object[] { presenterSearchService, userAuthService },
            new IInterceptor[]
        {
            excepInt
        });
    //Ninject.Extensions.Interception.DynamicProxyModule
    // I'm using directive ToConstant(..), and not To(..)
    //Bind my interface to the new proxy
    Bind(interfaceType).ToConstant(proxy).InThreadScope();

var proxy = Kernel.Get<IPolicySearchPresenter>();

返される型Castle.Proxies.FlexPolicySearchPresenterProxyは、私のリモート処理の実装で完全に機能するものとして返されます。

問題は、Ninject.Interception が のFlexPolicySearchPresenterProxy代わりに のインスタンスを返すようにするにはどうすればよいかということですIPolicySearchPresenterProxy。手動の Castle の方法を実行することで、別の方法でバインドしていることに注意してください。

        Bind(interfaceType).ToConstant(proxy).InThreadScope();

ninject 方法の代わりに:

Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>();

適切なタイプを取得するために、Ninject でバインディングを行う方法を変更する必要がありますか?

4

1 に答える 1

1

編集: Foo にプロパティ インジェクションを追加しました。

実用的な解決策がありますが、正直なところ、100% 満足しているわけではありません。とにかく、これは動作します:

class Program
{
    static void Main(string[] args)
    {
        var kernel = new StandardKernel();
        kernel.Bind<IFoo>().ToMethod(ctx => ctx.Kernel.Get<Foo>());

        kernel.Bind<Foo>().ToSelf().Intercept().With<SomeInterceptor>();

        var foo = kernel.Get<IFoo>();

        foo.DoSomething();

        Console.WriteLine(foo.GetType());

        Console.Read();
    }
}

public interface IFoo
{
    void DoSomething();
}

public class Foo : IFoo
{
    [Inject]
    public Bar Dependency { get; set; }

    public virtual void DoSomething()
    {
        Console.WriteLine("doing something with {0}", this.Dependency);
    }
}

public class SomeInterceptor : IInterceptor
{
    public SomeInterceptor()
    {
        Console.WriteLine("interceptor created");
    }

    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("before");
        invocation.Proceed();
        Console.WriteLine("after");
    }
}

public class Bar
{
    public override string ToString()
    {
        return "Bar (injected dependency)";
    }
}

結果の出力は次のとおりです。

interceptor created
before
doing something with Bar (injected dependency)
after

タイプは次のとおりです。

Castle.Proxies.FooProxy

.Bind().To().Bind().ToSelf().Intercept... は同じ結果にならないようです。理由は(まだ)わかりませんが、調査するつもりです。

コンストラクター引数の更新: Ninject 自体は、「継承ベースのクラス プロキシ」のみをサポートします。この場合、クラスにはデフォルト/空の ctor と「ターゲットのないインターフェイス プロキシ」が必要です。これは望ましくありません。

したがって、プロパティ インジェクションを「一度だけ」使用してもよろしいでしょうか。それ以外の場合は、独自のインターセプト ninject-magic を作成し、「ターゲットを指定したクラス プロキシ」を使用する必要があります ( http://docs.castleproject.org/Tools.Kinds-of-proxy-objects.ashx参照) 。 proxy with target" は、事前にそれらが何であるかを知る必要があるコンストラクター引数をサポートします (したがって、簡単な DI サポートはありません)。(動的プロキシがプロキシのコンストラクタを選択/作成した後、コンストラクタ引数を解決するためのフックが見つかりませんでした。)

于 2013-10-14T14:33:54.747 に答える