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 远程处理应用程序带来了问题。但是,如果我手动创建我的 Castle 代理:

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备注:即使“类带目标的代理”支持您需要事先知道它们是哪些构造函数参数(因此没有简单的 DI 支持)。(在动态代理为代理选择/创建构造函数后,我没有找到用于解析构造函数参数的钩子。)

于 2013-10-14T14:33:54.747 回答