Основываясь на этом решении , вы также можете сделать задачу класса Task наследованной от MarshalByRefObject.Это решит проблему с сериализацией, поскольку она передаст сериализованную ссылку между доменами приложений, которая будет использоваться для присоединения к событию.
public class ScanningTask : MarshalByRefObject
{
private class Loader : MarshalByRefObject
{
public void Load()
{
if (OnLoad != null)
OnLoad(this, EventArgs.Empty);
}
public event EventHandler OnLoad;
}
public void RunTask()
{
var domain = AppDomain.CreateDomain("LoadDomain");
var loader = (Loader)domain.CreateInstanceFromAndUnwrap(
typeof(Loader).Assembly.Location,
typeof(Loader).FullName);
loader.OnLoad += new EventHandler(loader_OnLoad);
loader.Load();
AppDomain.Unload(domain);
}
void loader_OnLoad(object sender, EventArgs e)
{
Console.Write("load event called");
}
}
Если по причинам существующей кодовой базы базовый класс Task не может быть унаследован отMarshalByRefObject, вашим решением может быть прокси-класс, который наследуется от Loader (следовательно, является самим MarshalByRefObject) и перенаправляет вызовы к фактическому распакованному экземпляру.
public class ScanningTask
{
private class Loader : MarshalByRefObject
{
public virtual void Load()
{
RaiseOnLoad(this);
}
protected void RaiseOnLoad(Loader loader)
{
if (OnLoad != null)
OnLoad(loader, EventArgs.Empty);
}
public event EventHandler OnLoad;
}
private class LoaderProxy : Loader
{
public readonly Loader Instance;
public LoaderProxy(Loader loaderInstance)
{
this.Instance = loaderInstance;
this.Instance.OnLoad += new EventHandler((sender, e) => RaiseOnLoad(this.Instance));
}
public override void Load()
{
this.Instance.Load();
}
}
public void RunTask()
{
var domain = AppDomain.CreateDomain("LoadDomain");
var loader = (Loader)domain.CreateInstanceFromAndUnwrap(
typeof(Loader).Assembly.Location,
typeof(Loader).FullName);
var proxy = new LoaderProxy(loader);
proxy.OnLoad += new EventHandler(loader_OnLoad);
loader.Load(); // same as proxy.Load()
AppDomain.Unload(domain);
}
void loader_OnLoad(object sender, EventArgs e)
{
Console.Write("load event called");
}
}