我正在尝试启用在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”未标记为可序列化。
可能是什么问题?
答案 0 :(得分:10)
.NET Remoting需要从子AppDomain访问PluginAppDomain_UnhandledException
。 PluginAppDomain_UnhandledException
是一个实例方法,因此子AppDomain需要通过此类的当前对象( this )访问它。有两种方法可以做到这一点。一种是从MarshalByRefObject派生类,这将允许通过代理从其他AppDomain访问它的实例。另一种方法是用SerializableAttribute来装饰类,让.NET Remoting知道这个类的实例可以序列化到其他AppDomains。这就是你得到序列化错误的原因。您的课程不是1)派生自MarshalByRefObject
而2)未标记为Serializable
。
据我所知,从不同的AppDomain
订阅此活动不是一个好主意。您甚至可以看到,即使您创建此类并且Logger
的类派生自MarshalByRefObject
,您仍然距离一个好的解决方案还有很长的路要走,因为您在AppDomains之间传递异常。因此,要实现此功能,您需要在AppDomains之间传递所有例外可序列化,并在两个AppDomains中加载其程序集。如果要隔离插件,这可能是一个问题。
如果我是你,我会首先让我的应用程序插件识别而不处理单独的AppDomain。隐瞒AppDomains和UnhandleExceptions的整个过程非常复杂。
然后我可以尝试你的方法但是使用MarshalByRefObject
派生对象(如果PluginAppDomain_UnhandledException是静态的,只有Logger就足够了)并且只将字符串传递给Logger
的方法。
否则我只是给插件单独登录或使用Windows事件日志。