创建应用程序域以与插件一起使用:"键入程序集未标记为可序列化

SeT*_*ToY 6 c# wpf plugins appdomain

我正在尝试启用在我的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);
    }
Run Code Online (Sandbox Code Playgroud)

但是附加UnhandledException事件会失败,但会出现异常:

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

可能是什么问题?

Pan*_*nis 10

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

据我所知,从不同的方面订阅此活动并不是一个好主意AppDomain.你会看到,即使你创建了这个类,并且LoggerMarshalByRefObject你那里得到的类仍然是一个很好的解决方案,因为你在AppDomains之间传递异常.因此,为了实现这一点,您需要在AppDomains之间传递的所有异常都是序列化的,并且它们在两个AppDomain中加载它们的程序集.如果要隔离插件,这可能是一个问题.

如果我是你,我会首先让我的应用程序插件知道而不处理单独的AppDomain.承认AppDomains和UnhandleExceptions的整个过程非常复杂.

然后我可以尝试你的方法但是使用MarshalByRefObject派生对象(如果PluginAppDomain_UnhandledException是静态的,只有Logger就足够了)并且只将字符串传递给Logger方法.

否则我只是给插件单独的日志或使用Windows事件日志.