Используя Ninject, как я могу использовать инъекцию свойств, Lazy<> и перехват, не встречая ошибок в castle.core?
Я создал простую программу в качестве PoC для старого проекта SharePoint On-Prem, использующего веб-формы ASP.NET. На его страницах я должен использовать инъекцию свойств, а для всего остального я могу использовать инжектор конструктора. Я также использую:
- 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.");
}
}
}
В результате я получаю следующую ошибку:
Необработанное исключение: System.TypeLoadException: не удалось загрузить тип 'Castle.Proxies.Func`2Proxy' из сборки 'DynamicProxyGenAssembly2, версия =0.0.0.0, Culture= нейтральный, PublicKeyToken=a621a9e7e5c32e69', так как родительский тип закрыт.
Если я удалю "Ленивый<>", он снова введет циклические зависимости. Если я уберу перехват, у него не будет никаких ошибок, но мне нужны перехватчики. И я должен использовать инъекцию свойств на страницах, потому что конструкторы страниц управляются веб-формами без каких-либо полезных хуков, как в MVC land. ПРИМЕЧАНИЕ. Веб-формы используются потому, что используется SharePoint 2013.
Любые идеи, как сохранить и перехват, и объявления Lazy<>, не обнаружив ошибки выше?
1 ответ
Я смог решить эту проблему, не добавляя перехватчики ко всему ядру, так как были некоторые типы, для которых не могли быть созданы прокси. Учитывая, что списки исключений были, вероятно, больше, чем я встречал, я выбрал следующий лучший вариант, который заключался в применении глобальных перехватчиков индивидуально к каждой привязке:
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.
Любые лучшие решения приветствуются!