创建与插件一起使用的应用程序域:“程序集中的类型未标记为可序列化

Posted

技术标签:

【中文标题】创建与插件一起使用的应用程序域:“程序集中的类型未标记为可序列化【英文标题】:Create App Domain to use with plugins: "Type in assembly is not marked as serializable 【发布时间】:2013-10-07 09:52:02 【问题描述】:

我正在尝试启用在我的 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”未标记为可序列化。

可能是什么问题?

【问题讨论】:

【参考方案1】:

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

据我所知,从不同的AppDomain 订阅此活动并不是一个好主意。你会看到,即使你将这个类和Logger 的类从MarshalByRefObject 派生出来,你仍然离一个好的解决方案还有很长的路要走,因为你在AppDomains 之间传递异常。因此,要使其正常工作,您需要在 AppDomain 之间传递的 所有 异常是 serializable 并且它们的程序集都加载到两个 AppDomain 中。如果您想隔离插件,这可能是个问题。

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

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

否则我只会为插件提供单独的日志或使用 Windows 事件日志。

【讨论】:

以上是关于创建与插件一起使用的应用程序域:“程序集中的类型未标记为可序列化的主要内容,如果未能解决你的问题,请参考以下文章

将现有的域类与 Spring Security 插件一起使用

将插件域与主域完全分离的最佳实践?

如何将骨干js与一些传统插件一起使用?

如何将 IntelliJ 与 Play Framework 和 Scala 一起使用

vsto 插件使用 excel 应用程序域

如何将 Amazon Route 53 与 Digital Ocean 水滴一起使用?