I'm trying to enable the capability of using plugins in my WPF application. As far as my understanding goes, I need (well, not need, but it's suggested) to create an additional app domain.
For this, I'm doing the following on startup in my 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);
}
But attaching the UnhandledException event fails with exception:
Type 'MyProject.App' in assembly 'MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1337' is not marked as serializable.
What could be the issue?
.NET Remoting needs to access PluginAppDomain_UnhandledException
from the child AppDomain. PluginAppDomain_UnhandledException
is an instance method and so the child AppDomain needs to access it through the current object (this) from this class. There are two ways to do this. One is to have the class derive from MarshalByRefObject which will allow it's instances to be accessed from other AppDomains via proxies. The other way it to decorate the class with the SerializableAttribute and let .NET Remoting know that instance of this class can be serialized to other AppDomains. This is why you get the serializable error. Your class does not 1) derive from MarshalByRefObject
and 2) is not marked as Serializable
.
As far as I know it isn't a very good idea to subscribe to this event from a different AppDomain
. You see even if you make this class and the class of Logger
to be derived from MarshalByRefObject
you will still be a long way from a good solution because you are passing exceptions between AppDomains. So for this to work you will need all exceptions passed between the AppDomains to be serializable and their assemblies loaded in both AppDomains. This might be a problem if you want to isolate plugins.
If I were you I would first make my application plugin-aware without dealing with separate AppDomains. The whole thing with concering AppDomains and UnhandleExceptions is quite complicated.
Then I might try your approach but with MarshalByRefObject
derived objects (only the Logger is enough if the PluginAppDomain_UnhandledException is made static) and pass only strings to the Logger
's methods.
Otherwise I would just give a separate log to the plugin or use the Windows Event Log.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With