Ninject Interception扩展正在创建该类的2个实例;有办法避免这种情况

问题描述 投票:1回答:2

我在DynamicProxy2中使用Ninject拦截扩展时遇到问题。本质上,创建了我的绑定对象的两个实例。我的绑定是:

this.Bind<TestInterface1>().ToSelf().Intercept().With(new ActionInterceptor(i => Console.WriteLine("In interceptor")));

第一个实例似乎是正常解析过程的一部分。第二个实例作为代理创建的一部分而创建,特别是在DynamicProxy3ProxyFactory.cs中。

reference.Instance = this.generator.CreateClassProxy(targetType, ProxyOptions, parameters, wrapper);

第二个实例似乎在Ninject上下文中替换了第一个实例(尽管我不确定100%如此),所以人们会相信一切都很好。第一个实例大约只有十亿分之一秒。不幸的是,我的构造函数并不是那么“干净”,并且两次运行都会引起混乱。当第二个实例的构造在Castle中完成时,我不知道是否有解决办法,但是可以建议(将构造函数重写并考虑下来:))。

ninject ninject-extensions
2个回答
1
投票

似乎您不了解使用动态代理进行拦截的工作方式。动态代理是从拦截的类/接口派生的新类,并将所有调用转发到拦截的类/接口。

例如

class A{ }
class AProxy : A {}

现在创建两个类的实例。由于AProxy调用了基本构造函数,因此您看到了两次构造函数调用。同样,您认为立即收集一个实例是错误的。它们的寿命完全相同。

最干净的解决方案是解决构造函数不能被两次调用的问题。这是一个强有力的信号,表明存在严重错误。其他可能性是使用2.3beta并使用接口而不是类,或将问题代码放入初始化方法中,该方法仅由真实类而非代理调用。


0
投票

我不认为雷莫的答案恰到好处。它看起来像“代理”如何工作。如果我们直接在下面的简单代码中使用Castle,则很明显,正在创建继承用户类的子类,而实际上并不需要第二个实例。 所以,由于我不知道的原因,两个实例似乎是Ninject拦截设计的最终结果。

两个用于Ninject拦截的实例看起来像Ninject设计的最终结果,其中Proxies Generator实际上是在实例创建后就起作用的“激活策略”(Ninject.Activation.Strategies.ActivationStrategy),因此它别无选择,但是创建另一个(代理)实例。原因也很公平,因为关于实例构造的所有细微差别仅是容器本身已知的,并且像这样的“扩展”(如不同的“激活策略”)被有意地与该方面分开。

void Main()
{
    var x = new ProxyGenerator().CreateClassProxy(typeof(Test), new Interceptor()) as Test;
}

public class Test
{
    public Test()
    {
        $"ctor for {GetType().FullName} base is {GetType().BaseType.FullName}".Dump();
    }
}

输出是(单行,单个实例):

Castle.Proxies.TestProxy库的ctor是UserQuery + Test

© www.soinside.com 2019 - 2024. All rights reserved.