查看代理生成代码:https://github.com/ninject/ninject.extensions.interception/blob/master/src/Ninject.Extensions.Interception.DynamicProxy/DynamicProxyProxyFactory.cs https://github.com/ninject/ninject.extensions.interception/blob/master/src/Ninject.Extensions.Interception.DynamicProxy/DynamicProxyProxyFactory.cs
if (targetType.IsInterface)
{
reference.Instance = this.generator.CreateInterfaceProxyWithoutTarget(targetType, additionalInterfaces, InterfaceProxyOptions, wrapper);
}
else
{
object[] parameters = context.Parameters.OfType<ConstructorArgument>()
.Select(parameter => parameter.GetValue(context, null))
.ToArray();
reference.Instance = this.generator.CreateClassProxy(targetType, additionalInterfaces, ProxyOptions, parameters, wrapper);
}
可以看到ninject的动态代理扩展只是传递ConstructorArgument
发送到 Castle 动态代理生成器。
因此,无需更改 ninject 扩展或创建自己的扩展,您需要将所有依赖项作为构造函数参数传递。您还可以尝试属性/方法注入是否有效(请参阅https://github.com/ninject/ninject/wiki/Injection-Patterns https://github.com/ninject/ninject/wiki/Injection-Patterns).
如果您控制代码,您可以向代理类添加接口,然后使用“与目标的接口代理 http://docs.castleproject.org/Tools.Kinds-of-proxy-objects.ashx“。这允许将代理实例化与目标(代理类)实例化分离——>目标可以注入依赖项ctor,而无需对ninject(-扩展)进行任何更改。
澄清:
具有应代理的以下类:
public interface IBar { }
public class Foo
{
public Foo(IBar bar)
{
}
}
以及以下绑定:
Bind<Foo>().ToSelf().Intercept().With<SomeInterceptor>();
Bind<IBar>().To<Bar>();
然后检索一个Foo
从 ninject 容器中:
IResolutionRoot.Get<Foo>();
行不通的。
将所有构造函数参数放在 ninject 上下文中以使其正常工作
但是,我们可以改变检索Foo
使其发挥作用:
var bar = IResolutionRoot.Get<IBar>();
IResolutionRoot.Get<Foo>(new ConstructorArgument("bar", bar);
现在这是次优的,因为 ninject 不会自动执行依赖项解析。
向代理类添加接口以使其更好地工作
我们可以通过使用“带有目标的接口代理”来解决这个问题。
首先,我们向代理类添加一个接口:
public interface IFoo{ }
public class Foo : IFoo
{
public Foo(IBar bar)
{
}
}
然后我们将绑定更改为:
Bind<IFoo>().To<Foo>().Intercept().With<SomeInterceptor>();
然后检索一个Foo
从 ninject 容器中:
IResolutionRoot.Get<Foo>();
works.
另一个可能更简单(&丑陋?)的解决方案根据@Daniel 的说法,这是有效的:
添加两个构造函数到代理类型:
- one
protected
不带参数的构造函数。这个是DynamicProxy创建代理的。
- one
public
/internal
带有参数的构造函数,由 ninject 用来实例化代理类型。
Ninject 将自动选择具有最多可解析参数的构造函数。