在使用对象远程处理MarshalByRefObj时为什么要使用委托?

时间:2018-11-11 13:29:54

标签: c# delegates marshalling

我的应用程序允许插件,我有一个插件必须继承的Core类(MarshalByRefObj),并且该类提供了各种功能。现在我的问题是,当此类在主应用程序域上实例化并传递到其他应用程序域中的插件时,在这种情况下使用委托有什么好处:

public class Core : MarshalByRefObject
{
    public void DoSomething()
    {
         MyMainApp.Delegate1("SomeMethod", "Test");
    }
}

如您所见,我的核心类在MyMainApp上调用了一个委托方法。我也可以只做MyMainApp.SomeMethod("test")

但是,在许多有关远程处理和插件系统如何工作的在线示例中,每个人似乎都在使用委托。有什么具体原因吗?有人可以给我一个更实际的例子说明为什么吗?

2 个答案:

答案 0 :(得分:0)

在大多数情况下,用户界面中的控件是由主线程创建的,除非您有意在另一个线程中创建它们。这是重要的一点:只有创建控件的线程才能访问该控件。

如果您直接调用DoSomething,并且DoSomething中的代码想要与UI控件交互,则将不允许它,并且您将获得异常。 MyMainApp.Delegate1("DoSomething"等效于:请在主线程上执行指定的方法。现在它可以访问UI控件。

还有其他原因,但这是要记住的最重要的方面。有关更多信息,请参见MSDN

答案 1 :(得分:0)

好处之一是,传递给MyMainApp.Delegate1的信息将被序列化以便从插件appdomain传输到main-appdomain。 Delegate1方法将在主域中执行DoSomething。它们不共享内存(因此无法直接访问对象实例)。因此,您可以在另一个appdomain上动态运行方法。如果通过反射完成,则插件可能能够运行未列出的方法。

我不想使用这种类型的构造,因为没有对调用方法的编译时检查。我宁愿使用卫星装配体中的接口。 (以防止main-appdomain获得对插件程序集的引用/加载,因此无法再将其卸载)


另一件事: 如果您直接致电MyMainApp.SomeMethod("test")。这意味着插件必须知道插件加载程序的定义。这意味着您(从插件)与“父”应用程序紧密耦合。这使得整个插件结构“无用”。您可以通过在MyMainApp上实现一个ISupportSomeMethod接口来解决此问题,该接口在一个卫星组件中定义,该组件由两个mainapp和该插件使用。如果您的MyMainApp没有实现ISupportSomeMethod接口,则该插件与该程序不兼容。这样,您的MyMainApp就可以支持多种插件结构。


在这种情况下,您希望使用事件结构。因为子对象想要触发其父对象的方法。糟糕的跨域事件调用没有用,因为您的主模块将加载程序集并且无法将其卸载。您可以为此编写一个proxi类。