Перехват событий с помощью Castle DynamicProxy

В поиске в Google я не могу найти пример перехвата события на проксируемом типе, и, похоже, он не работает для меня. Есть ли способ сделать это (т. Е. Использовать IInterceptor при вызове события)?


person Jeff    schedule 04.06.2010    source источник


Ответы (2)


Я сомневаюсь. Castle Dynamic Proxy работает, перехватывая звонки, сделанные через прокси. События на прокси не производятся. Это обратные вызовы, обрабатываемые платформой .NET.

person PatrickSteele    schedule 04.06.2010
comment
Это правильно. С DP вы можете перехватывать методы, включая подписку на события и отмену подписки, но это все. - person Krzysztof Kozmic; 05.06.2010
comment
Спасибо, мое решение ниже выполняет то, что я искал, поэтому в этом нет необходимости. - person Jeff; 06.06.2010

В итоге я использовал событие ComponentCreated, а затем добавил динамический обработчик событий с DynamicMethod, чтобы выполнить то, что я хотел:

private static readonly MethodInfo internalPublishEventMethod =
    typeof(EventPublisher).GetMethod("PublishEvent", BindingFlags.Static | BindingFlags.NonPublic);

private void Container_ComponentCreated(global::Castle.Core.ComponentModel model, object instance)
{
    if (instance != null)
    {
        Type type = instance.GetType();

        var eventPublisherAttribute = type.GetAttribute<EventPublisherAttribute>();

        if (eventPublisherAttribute != null)
        {
            foreach (EventInfo ei in type.GetEvents())
            {
                if (eventPublisherAttribute.PublishAllEvents || ei.GetCustomAttributes(typeof(PublishedEventAttribute), false).Length > 0)
                {
                    // emit an event handler

                    MethodInfo invoke = ei.EventHandlerType.GetMethod("Invoke");
                    Type[] parameters = invoke.GetParameters().Select(p => p.ParameterType).ToArray();

                    var method = new DynamicMethod(string.Empty, null, parameters, instance.GetType(),
                                                   true);
                    ILGenerator generator = method.GetILGenerator();
                    // sender
                    generator.Emit(OpCodes.Ldarg_0);
                    // args
                    generator.Emit(OpCodes.Ldarg_1);
                    // topic
                    generator.Emit(OpCodes.Ldstr, ei.Name);
                    generator.Emit(OpCodes.Call, internalPublishEventMethod);
                    generator.Emit(OpCodes.Ret);

                    Delegate d = method.CreateDelegate(ei.EventHandlerType);
                    ei.AddEventHandler(instance, d);
                }
            }
        }
    }
}

private static void PublishEvent(object sender, EventArgs e, string topic)
{
    if (e != null)
    {
    // do stuff
    }
}
person Jeff    schedule 04.06.2010
comment
У меня такая же проблема. Куда вы положили этот обработчик событий? - person Mike Therien; 03.08.2010
comment
6 лет спустя ... событие связано с ядром контейнеров, предоставленным IKernelEvents. github.com/castleproject/Windsor/blob/master/docs/ - person Konstantin; 07.12.2016