使用Ninject,如何使用属性注入、Lazy<>、拦截而不遇到castle.core中的错误?
Using Ninject, how can I use property injection, Lazy<>, and interception without encountering errors in castle.core?
我为使用 ASP.NET Web 表单的旧 SharePoint On-Prem 项目创建了一个简单的程序作为 PoC。在它的页面中,我必须使用 属性 注入,对于其他所有内容,我可以使用构造函数注入。我也在使用:
- Ninject.Extensions.Factory
- Ninject.Extensions.Interception
- Ninject.Extensions.Interception.DynamicProxy
在我添加拦截器并使用 Lazy<> 解决一些循环依赖之前,一切都运行良好。为了在示例中简化这一点,我编写了以下示例作为控制台应用程序:
public class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new DynamicProxyModule(),
new FuncModule());
kernel.Bind<ISomeClass>().To<SomeClass>();
kernel.Bind<IOtherClass>().To<OtherClass>();
kernel.Bind<IAnotherClass>().To<AnotherClass>();
kernel.Intercept(p => true).With(new ClassInterceptor()); // Removing this works, but I need the interceptors.
ISomeClass someClass = kernel.TryGet<ISomeClass>();
someClass.Foo();
}
public interface ISomeClass
{
void Foo();
}
public class SomeClass : ISomeClass
{
[Inject]
public IOtherClass OtherClass { get; set; }
public SomeClass() { }
public void Foo()
{
Console.WriteLine("Foo");
this.OtherClass.Bar();
}
}
public interface IOtherClass
{
void Bar();
}
public class OtherClass : IOtherClass
{
private readonly Lazy<IAnotherClass> _anotherClass;
public IAnotherClass AnotherClass { get { return this._anotherClass.Value; } }
public OtherClass(Lazy<IAnotherClass> anotherClass)
{
this._anotherClass = anotherClass;
}
public void Bar()
{
Console.WriteLine("Bar");
}
}
public interface IAnotherClass
{
void FooBar();
}
public class AnotherClass : IAnotherClass
{
private readonly Lazy<IOtherClass> _otherClass;
public IOtherClass OtherClass { get { return this._otherClass.Value; } }
public AnotherClass(Lazy<IOtherClass> otherClass)
{
this._otherClass = otherClass;
}
public void FooBar()
{
Console.WriteLine("FooBar");
this.OtherClass.Bar();
}
}
public class ClassInterceptor: SimpleInterceptor
{
public ClassInterceptor() { }
protected override void BeforeInvoke(IInvocation invocation)
{
base.BeforeInvoke(invocation);
Console.WriteLine("I'm doing stuff before.");
}
protected override void AfterInvoke(IInvocation invocation)
{
base.BeforeInvoke(invocation);
Console.WriteLine("I'm doing stuff after.");
}
}
}
因此,我收到以下错误:
Unhandled Exception: System.TypeLoadException: Could not load type 'Castle.Proxies.Func`2Proxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69' because the parent type is sealed.
如果我删除"Lazy<>",它会重新引入循环依赖。如果我删除拦截,它不会有任何错误,但我需要拦截器。而且,我必须在页面上使用 属性 注入,因为页面的构造函数由 webforms 管理,没有像 MVC 领域那样有用的挂钩。注意:正在使用网络表单,因为正在使用 SharePoint 2013。
关于如何在不遇到上述错误的情况下同时保留拦截和 Lazy<> 声明的任何想法?
我能够通过不将拦截器添加到整个内核来解决这个问题,因为有些类型无法为它们创建代理。考虑到排除列表可能比我遇到的要多,我选择了下一个最佳选择,即对每个绑定单独应用全局拦截器:
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new DynamicProxyModule(),
new FuncModule());
AddInterceptors(kernel.Bind<ISomeClass>().To<SomeClass>());
AddInterceptors(kernel.Bind<IOtherClass>().To<OtherClass>());
AddInterceptors(kernel.Bind<IAnotherClass>().To<AnotherClass>());
//kernel.Intercept(p => true).With(new ClassInterceptor());
ISomeClass someClass = kernel.TryGet<ISomeClass>();
someClass.Foo();
}
private static void AddInterceptors<T>(IBindingWhenInNamedWithOrOnSyntax<T> binding)
{
binding.Intercept(p => true).With(new ClassInterceptor());
/* ... other interceptors ... */
}
感谢您让我知道试图为 Lazy 和 T 创建代理的拦截扩展发生了什么,@BatteryBackupUnit。
欢迎大家提出更好的方案!
我为使用 ASP.NET Web 表单的旧 SharePoint On-Prem 项目创建了一个简单的程序作为 PoC。在它的页面中,我必须使用 属性 注入,对于其他所有内容,我可以使用构造函数注入。我也在使用:
- Ninject.Extensions.Factory
- Ninject.Extensions.Interception
- Ninject.Extensions.Interception.DynamicProxy
在我添加拦截器并使用 Lazy<> 解决一些循环依赖之前,一切都运行良好。为了在示例中简化这一点,我编写了以下示例作为控制台应用程序:
public class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new DynamicProxyModule(),
new FuncModule());
kernel.Bind<ISomeClass>().To<SomeClass>();
kernel.Bind<IOtherClass>().To<OtherClass>();
kernel.Bind<IAnotherClass>().To<AnotherClass>();
kernel.Intercept(p => true).With(new ClassInterceptor()); // Removing this works, but I need the interceptors.
ISomeClass someClass = kernel.TryGet<ISomeClass>();
someClass.Foo();
}
public interface ISomeClass
{
void Foo();
}
public class SomeClass : ISomeClass
{
[Inject]
public IOtherClass OtherClass { get; set; }
public SomeClass() { }
public void Foo()
{
Console.WriteLine("Foo");
this.OtherClass.Bar();
}
}
public interface IOtherClass
{
void Bar();
}
public class OtherClass : IOtherClass
{
private readonly Lazy<IAnotherClass> _anotherClass;
public IAnotherClass AnotherClass { get { return this._anotherClass.Value; } }
public OtherClass(Lazy<IAnotherClass> anotherClass)
{
this._anotherClass = anotherClass;
}
public void Bar()
{
Console.WriteLine("Bar");
}
}
public interface IAnotherClass
{
void FooBar();
}
public class AnotherClass : IAnotherClass
{
private readonly Lazy<IOtherClass> _otherClass;
public IOtherClass OtherClass { get { return this._otherClass.Value; } }
public AnotherClass(Lazy<IOtherClass> otherClass)
{
this._otherClass = otherClass;
}
public void FooBar()
{
Console.WriteLine("FooBar");
this.OtherClass.Bar();
}
}
public class ClassInterceptor: SimpleInterceptor
{
public ClassInterceptor() { }
protected override void BeforeInvoke(IInvocation invocation)
{
base.BeforeInvoke(invocation);
Console.WriteLine("I'm doing stuff before.");
}
protected override void AfterInvoke(IInvocation invocation)
{
base.BeforeInvoke(invocation);
Console.WriteLine("I'm doing stuff after.");
}
}
}
因此,我收到以下错误:
Unhandled Exception: System.TypeLoadException: Could not load type 'Castle.Proxies.Func`2Proxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69' because the parent type is sealed.
如果我删除"Lazy<>",它会重新引入循环依赖。如果我删除拦截,它不会有任何错误,但我需要拦截器。而且,我必须在页面上使用 属性 注入,因为页面的构造函数由 webforms 管理,没有像 MVC 领域那样有用的挂钩。注意:正在使用网络表单,因为正在使用 SharePoint 2013。
关于如何在不遇到上述错误的情况下同时保留拦截和 Lazy<> 声明的任何想法?
我能够通过不将拦截器添加到整个内核来解决这个问题,因为有些类型无法为它们创建代理。考虑到排除列表可能比我遇到的要多,我选择了下一个最佳选择,即对每个绑定单独应用全局拦截器:
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new DynamicProxyModule(),
new FuncModule());
AddInterceptors(kernel.Bind<ISomeClass>().To<SomeClass>());
AddInterceptors(kernel.Bind<IOtherClass>().To<OtherClass>());
AddInterceptors(kernel.Bind<IAnotherClass>().To<AnotherClass>());
//kernel.Intercept(p => true).With(new ClassInterceptor());
ISomeClass someClass = kernel.TryGet<ISomeClass>();
someClass.Foo();
}
private static void AddInterceptors<T>(IBindingWhenInNamedWithOrOnSyntax<T> binding)
{
binding.Intercept(p => true).With(new ClassInterceptor());
/* ... other interceptors ... */
}
感谢您让我知道试图为 Lazy 和 T 创建代理的拦截扩展发生了什么,@BatteryBackupUnit。
欢迎大家提出更好的方案!