如何通过反射添加BackgroundWorker RunWorkerCompleted事件?

发布于 2024-07-27 02:59:45 字数 898 浏览 7 评论 0原文

通常我会去:

bgwExportGrid.RunWorkerCompleted += ReportManager.RunWorkerCompleted;

ReportManager 类是一个静态类,包含我想要使用的事件处理程序。

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

现在我已经创建了一个BackgroundWorker,并希望附加ReportManager 中定义的RunWorkerCompleted 事件。 但是,无法引用 ReportManager,否则会发生循环引用,因此需要反射。

任何帮助将不胜感激。

我已经查看了以下内容,但还没有走得太远:

        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;

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

女皇必胜 2024-08-03 02:59:45

我认为,如果您将 ReportManager 中的接口抽象为两个程序集都可以引用的接口,那么您的代码将来会更容易维护。 但是,如果这不适合您,我认为您正在尝试实现类似的目标:

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 
        }
    }
}

请注意 Form1EventHandlers 之间没有“硬”引用> 类,因此它可以是驻留在任何其他程序集中的任何其他类; 事件处理程序是根据类型名称和方法名称(当然,必须具有正确的签名)创建和附加的。

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).

蝶舞 2024-08-03 02:59:45

更新的答案:

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);

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);
挖个坑埋了你 2024-08-03 02:59:45

设法让它工作。 ReportManager 是一个静态类,因此不需要使用 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");

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");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文