views:

739

answers:

3

Normally I would go:

bgwExportGrid.RunWorkerCompleted += ReportManager.RunWorkerCompleted;

The ReportManager class is a static class containing the event handler I want to use.

public static class ReportManager
{
        public static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        ...
        }
}

Now I have created a BackgroundWorker and want to attach the RunWorkerCompleted event as defined in ReportManager. However ReportManager cannot be referenced as otherwise a cyclic reference happens therefore reflection is needed.

Any help would be greatly appreciated.

I've looked at the following but haven't gotten very far:

        Assembly assem = Utils.GetAssembly("WinUI.Reporting.Common.dll");
        Type reportManagerType = assem.GetModule("WinUI.Reporting.Common.dll").GetType("WinUI.Reporting.Common.ReportManager");
        EventInfo evWorkerCompleted = reportManagerType.GetEvent("RunWorkerCompleted");
        Type tDelegate = evWorkerCompleted.EventHandlerType;
A: 

Updated answer:

Assembly assem = Utils.GetAssembly("WinUI.Reporting.Common.dll");

Type reportManagerType = assem.GetModule("WinUI.Reporting.Common.dll").GetType("WinUI.Reporting.Common.ReportManager");

// obtain the method info
MethodInfo mi = reportManagerType.GetMethod("RunWorkerCompleted", 
                                            BindingFlags.Static | BindingFlags.Public);

// create a delegate that we can further register with the event
Delegate handler = Delegate.CreateDelegate(reportManagerType , mi);

// get the event info from the export grid object
EventInfo evWorkerCompleted = bgwExportGrid.GetType().GetEvent("RunWorkerCompleted");

// invoke the event
evWorkerCompleted.AddEventHandler(bgwExportGrid, handler);
arul
I cannot do the above as I cannot reference the ReportManager class at all, which is why I need to use reflection.
Your question is rather ambiguous, what are you trying to achieve?
arul
Normally you would go bgwExportGrid.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ReportManager.RunWorkerCompleted);Yet in my case I cannot even reference ReportManager and therefore need to use reflection - which I don't know how to in this case.
+1  A: 

I think your code would be easier to maintain in the future if you would instead abtract the interface out of the ReportManager into an interface that both assemblies can reference. But, if that is not an option for you, I think that you are trying to achieve something like this:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            AttachEventHandler(backgroundWorker1,
                  Type.GetType("WindowsFormsApplication1.EventHandlers"),
                  "RunWorkerCompleted");
            backgroundWorker1.RunWorkerAsync();
        }

        private void AttachEventHandler(BackgroundWorker bgw, Type targetType,
            string eventHandlerMethodName)
        {
            object targetInstance = Activator.CreateInstance(targetType);
            bgw.RunWorkerCompleted += 
                (RunWorkerCompletedEventHandler)Delegate.CreateDelegate(
                    typeof(RunWorkerCompletedEventHandler), 
                    targetInstance, eventHandlerMethodName);
        }

    }

    public class EventHandlers
    {
        public void RunWorkerCompleted(object sender, 
            System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            // do something 
        }
    }
}

Note how there is no "hard" reference between Form1 and the EventHandlers class, so that could be any other class residing in any other assembly; the event handler is created and attached based on the name of the type and the name of the method (which, naturally, must have the correct signature).

Fredrik Mörk
A: 

Managed to get it working. ReportManager is a static class therefore there is no need to use Activator.CreateInstance.

        Assembly assem = Utils.GetAssembly("WinUI.Reporting.Common.dll");
        Type reportManagerType = assem.GetModule("WinUI.Reporting.Common.dll").GetType("WinUI.Reporting.Common.ReportManager");
        bgwExportGrid.RunWorkerCompleted += (RunWorkerCompletedEventHandler)Delegate.CreateDelegate(typeof(RunWorkerCompletedEventHandler), reportManagerType, "RunWorkerCompleted");