创建与插件一起使用的应用程序域:“程序集中的类型未标记为可序列化
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_UnhandledException
。 PluginAppDomain_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 插件一起使用