views:

39

answers:

2

I know about EventInfo.AddEventHandler(...) method which can be used to attach handler to an event. But what should be done if i can not even define proper signature of the event handler, as in, i don't even have reference to the event args expected by the handler?

I will explain the problem with the proper code.

// Scenario when i have everything available in my solution, Zero Reflection Scenario.

internal class SendCommentsManager
    {
        public void Customize(IRFQWindowManager rfqWindowManager)
        {
            rfqWindowManager.SendComment += HandleRfqSendComment;
        }

        private void HandleRfqSendComment(object sender, SendCommentEventArgs args)
        {
            args.Cancel = true;
        }
    }

Now, i want to achieve the same objective by using reflection. I have been able to figure out most of it but when i attach a delegate to the event (using AddEventHandler) it throws "Error binding to target method." exception.

I understand the reason behind this exception, attaching a wrong delegate to an event. But there must be some way to achieve this.

 internal class SendCommentsManagerUsingReflection
    {

        public void Customize(IRFQWindowManager rfqWindowManager)
        {
            EventInfo eventInfo = rfqWindowManager.GetType().GetEvent("SendComment");
            eventInfo.AddEventHandler(rfqWindowManager,
                                      Delegate.CreateDelegate(eventInfo.EventHandlerType, this, "HandleRfqSendComment"));
 //<<<<<<<<<<ABOVE LINE IS WHERE I AM GOING WRONG>>>>>>>>>>>>>>
        }

        private void HandleRfqSendComment(object sender, object args)
        {
            Type sendCommentArgsType = args.GetType();
            PropertyInfo cancelProperty = sendCommentArgsType.GetProperty("Cancel");
            cancelProperty.SetValue(args, true, null);
        }

    }
A: 

You may want to consider the observer pattern: http://www.dofactory.com/Patterns/PatternObserver.aspx

Brian
A: 

I think your code is failing because the HandleRfqSendComment is private. Instead you could directly create a delegate to that method, without passing its name to CreateDelegate. You would then need to convert the delegate to the required type, using the following method :

public static Delegate ConvertDelegate(Delegate originalDelegate, Type targetDelegateType)
{
    return Delegate.CreateDelegate(
        targetDelegateType,
        originalDelegate.Target,
        originalDelegate.Method);
}

In your code, you could use this method as follows :

EventInfo eventInfo = rfqWindowManager.GetType().GetEvent("SendComment");
Action<object, object> handler = HandleRfqSendComment;
Delegate convertedHandler = ConvertDelegate(handler, eventInfo.EventHandlerType);
eventInfo.AddEventHandler(rfqWindowManager, convertedHandler);
Thomas Levesque