Расширение Ninject Interception создает 2 экземпляра класса; есть ли способ избежать этого

У меня проблема с использованием расширения перехвата Ninject с DynamicProxy2. По сути, создаются два экземпляра моего объекта привязки. Моя привязка:

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, я не знаю, есть ли способ обойти это, но буду признателен за любой совет (переписывание конструкторов было продумано и сбито :)).


person basilard99    schedule 12.07.2011    source источник


Ответы (2)


Похоже, вы не понимаете, как работает перехват с использованием динамических прокси. Динамический прокси — это новый класс, производный от перехваченного класса/интерфейса и перенаправляющий все вызовы перехваченному классу/интерфейсу.

e.g.

class A{ }
class AProxy : A {}

Теперь создается экземпляр обоих классов. Поскольку AProxy вызывает базовый конструктор, вы видите два вызова конструктора. Также ваше предположение о том, что один экземпляр немедленно собирается, неверно. У них точно такой же срок службы.

Самое чистое решение - решить проблему, состоящую в том, что ваш конструктор нельзя вызывать дважды. Это явный признак того, что что-то ужасно не так. Другие возможности включают использование 2.3beta и использование интерфейса вместо класса или помещение проблемного кода в метод инициализации, который вызывается только реальным классом, но не прокси.

person Remo Gloor    schedule 16.07.2011
comment
Спасибо за ваш ответ. ты город - person basilard99; 19.07.2011
comment
Извиняюсь. Пытаюсь отредактировать это на DROID. Спасибо за Ваш ответ. Мы решили использовать инициализатор на данный момент. - person basilard99; 19.07.2011

Я не думаю, что ответ Ремо точно по делу. Не похоже, что это "как работают прокси". Если бы мы использовали 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();
    }
}

Вывод (одна строка, один экземпляр):

ctor для Castle.Proxies.TestProxy базой является UserQuery+Test

person Eugene D. Gubenkov    schedule 12.02.2020