6

我正在尝试启用在我的 WPF 应用程序中使用插件的功能。据我了解,我需要(嗯,不需要,但建议)创建一个额外的应用程序域。

为此,我在 App.xaml.cs 中启动时执行以下操作:

    private void LoadPlugins()
    {
        // Create and polish plugin app domain
        AppDomain pluginAppDomain = AppDomain.CreateDomain("MyProject Plugin Container", null);
        pluginAppDomain.UnhandledException += PluginAppDomain_UnhandledException;

        //TODO: Load plugins from dlls
    }

    private void PluginAppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Logger.FatalException("PluginAppDomain", e.ExceptionObject as Exception);
    }

但附加 UnhandledException 事件失败并出现异常:

在程序集“MyProject,Version=1.0.0.0,Culture=neutral,PublicKeyToken=1337”中键入“MyProject.App”未标记为可序列化。

可能是什么问题?

4

1 回答 1

10

.NET Remoting 需要PluginAppDomain_UnhandledException从子 AppDomain 访问。PluginAppDomain_UnhandledException是一个实例方法,因此子 AppDomain 需要通过此类的当前对象 ( this ) 访问它。有两种方法可以做到这一点。一种是从MarshalByRefObject派生类,这将允许通过代理从其他 AppDomain 访问它的实例。另一种方法是用SerializableAttribute装饰类并让 .NET Remoting 知道此类的实例可以序列化到其他 AppDomain。这就是您收到可序列化错误的原因。您的类不 1) 派生自MarshalByRefObject和 2) 未标记为Serializable.

据我所知,从不同的AppDomain. 您会看到,即使您创建了此类以及Logger要从MarshalByRefObject您派生的类,距离一个好的解决方案还有很长的路要走,因为您在 AppDomain 之间传递异常。因此,要使其正常工作,您需要在 AppDomain 之间传递的所有异常都是可序列化的,并且它们的程序集都加载到两个 AppDomain 中。如果您想隔离插件,这可能是个问题。

如果我是你,我会首先让我的应用程序插件感知而不处理单独的 AppDomain。关于 AppDomains 和 UnhandleExceptions 的整个事情是相当复杂的。

然后我可能会尝试您的方法,但使用MarshalByRefObject派生对象(如果 PluginAppDomain_UnhandledException 设为静态,则只有 Logger 就足够了)并且仅将字符串传递给Logger's 方法。

否则我只会给插件一个单独的日志或使用 Windows 事件日志。

于 2013-10-08T08:22:47.093 回答