创建应用程序域以与插件一起使用:“程序集中的键入未标记为可序列化
本文关键字:集中 序列化 记为 程序集 程序 插件 应用程序域 一起 创建 | 更新日期: 2023-09-27 18:34:08
我正在尝试启用在我的 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,版本=1.0.0.0,区域性=中性,公钥令牌=1337"中的类型"MyProject.App"未标记为可序列化。
可能是什么问题?
NET 远程处理需要从子 AppDomain 访问PluginAppDomain_UnhandledException
。 PluginAppDomain_UnhandledException
是一个实例方法,因此子 AppDomain 需要通过此类中的当前对象 (this( 访问它。有两种方法可以做到这一点。一种是让类派生自 MarshalByRefObject,这将允许通过代理从其他 AppDomain 访问它的实例。另一种方式是使用 SerializableAttribute 修饰类,并让 .NET 远程处理知道此类的实例可以序列化到其他 AppDomain。这就是您收到可序列化错误的原因。您的类不是 1( 派生自 MarshalByRefObject
和 2( 未标记为 Serializable
。
据我所知,从不同的AppDomain
订阅此事件不是一个好主意。您会看到,即使您将此类和要从MarshalByRefObject
派生的Logger
类,您仍然离一个好的解决方案还有很长的路要走,因为您要在 AppDomain 之间传递异常。因此,要使其正常工作,您需要在应用程序域之间传递的所有异常都是可序列化的,并且它们的程序集在两个应用程序域中加载。如果要隔离插件,这可能是一个问题。
如果我是你,我会首先让我的应用程序插件感知,而不处理单独的应用程序域。Conconcy AppDomains 和 UnhandleExceptions 的整个事情非常复杂。
然后我可能会尝试你的方法,但使用MarshalByRefObject
派生对象(如果PluginAppDomain_UnhandledException是静态的,只有记录器就足够了(,并且只将字符串传递给Logger
的方法。
否则,我只会为插件提供单独的日志或使用 Windows 事件日志。