Castle DynamicProxy прерывает прослушивание событий

#c# #castle-windsor #castle #castle-dynamicproxy

#c# #замок-Виндзор #castle #замок-DynamicProxy

Вопрос:

История началась так, я использовал средство Castle EventWiring для определения прослушивателей событий в моих классах, и это работало нормально, раньше я вызывал такие события:

 if (null != BlaBlaEvent)
{
    BlaBlaEvent(someData);
}
  

Недавно я столкнулся с бизнес-требованием и подумал, что, вероятно, лучшим решением будет использовать шаблон прокси, поэтому я использовал DynamicProxy в своей функции разрешения IoC (небольшая оболочка для Castle Windsor) У меня есть следующий код:

 T componenet = _container.Resolve<T>();

var gen = new ProxyGenerator();

if (typeof(T).IsClass)
{
    return gen.CreateClassProxyWithTarget(componenet, _container.Resolve<StashInterceptor>());
}
else
{
    return gen.CreateInterfaceProxyWithTarget(componenet, _container.Resolve<StashInterceptor>());
}
  

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

проблема теперь в том, что события в конкретном классе не имеют прослушивателей (хотя в конфигурациях указано, что они есть).

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

У кого-нибудь есть идея?

Вот мои конфигурации castle xml в web.config:

 <castle>
    <facilities>
        <facility id="event.wiring" type="Castle.Facilities.EventWiring.EventWiringFacility, Castle.Facilities.EventWiring" />
    </facilities>
<components>
  <component id="SomeInterceptor" type="Namespace.SomeInterceptor, MyAssembly" />

  <component id="SomePublisher" type="Namespace.SomePublisher, MyAssembly">
    <subscribers>
      <subscriber id="SomeSubscriber" event="SomeEvent" handler="OnSomeEvent" />
    </subscribers>
  </component>
  <component id="SomeSubscriber" type="Namespace.SomeSubscriber, MyAssembly" />
</components>
  

Ответ №1:

Примечание: проблема не в xml или свободной конфигурации, а в том, что вы генерируете свои прокси через Castle.DynamicProxy самостоятельно. Если вы вместо этого используете контейнер и регистрируете свои перехватчики, используя функциональность в вашем контейнере (который, кстати, использует DynamicProxy), это сработает.

Не уверен, что именно вы пытаетесь сделать, но, как показано ниже, не проблема зарегистрировать перехватчик в прослушивателе и заставить его перехватывать вызовы методов прослушивателя и в то же время использовать функциональность подключения событий. Это windsor 3.3

 public class EventWiringFacilityTests
{
    public void RegisterInterceptorWithListenerAndMakeSureListenerSubscribes()
    {
        var container = new WindsorContainer();

        container.AddFacility<EventWiringFacility>();

        container.Register(Component.For<SomeInterceptor>());

        container.Register(
           Component.For<SimplePublisher>()
              .PublishEvent(p => p.Event  = null,
                            x => x.To<SimpleListener>("foo", l => l.OnEvent(null, null))),
           Component.For<SimpleListener>().Interceptors<SomeInterceptor>().Named("foo"));

        var someInterceptor = container.Resolve<SomeInterceptor>();

        var simpleListener = container.Resolve<SimpleListener>();
        Assert.That(simpleListener.EventHasHappened, Is.False);

        var simplePublisher = container.Resolve<SimplePublisher>();
        simplePublisher.Trigger();

        Assert.That(simpleListener.EventHasHappened);

        simpleListener.Snap();
        Assert.That(someInterceptor.Intercepted);
    }
}

public class SomeInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Intercepted = true;
        invocation.Proceed();
    }

    public bool Intercepted { get; set; }
}

public class SimplePublisher
{
    public event EventHandler Event;

    public void Trigger()
    {
        if (Event != null)
        {
            Event(this, new EventArgs());
        }
    }
}

public class SimpleListener
{
    public bool EventHasHappened { get; set; }

    public void OnEvent(object sender, EventArgs e)
    {
        EventHasHappened = true;
    }

    public virtual void Snap()
    {

    }
}
  

Комментарии:

1. Спасибо за ответ, но, похоже, со мной это не работает, я использую отображение xml, я отредактирую вопрос, чтобы показать вам свои конфигурации.