作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有两个应用程序域,一个父域创建子域。在子域中,有一个 MarshalByRef
对象,使用 .NET Remoting 进行通信。在父域中运行的对象调用远程对象的包装器作为应用程序功能的一部分:
public class ScanningTask : Task
{
private class Loader : MarshalByRef
{
public void Load(IEnumerable<string> paths)
{
...
}
public event EventHandler<LoadEventArgs> OnLoad;
}
public void RunTask()
{
var domain = AppDomain.CreateDomain("LoadDomain");
var loader = (Loader)domain.CreateInstanceFromAndUnwrap(
typeof(Loader).Assembly.Location,
typeof(Loader).FullName);
loader.Load(...);
AppDomain.Unload(domain);
}
}
为简洁起见,删除了大部分代码。
此 Loader
对象公开了我想要在父域中捕获的 OnLoad
事件。如果我只是添加一个事件处理程序委托(delegate),它会尝试将 ScanningTask 序列化到子域中,并抛出有关它不可序列化的异常。
我真正想要的是跨域交流该事件。有什么聪明的建议吗?
最佳答案
基于this solution ,您也可以使您的 Task 类任务继承自 MarshalByRefObject 。这将解决序列化问题,因为它将传递一个跨 AppDomain 序列化引用,该引用将用于附加到事件。
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");
}
}
关于.net - 如何在应用程序域之间传递事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5817521/
我是一名优秀的程序员,十分优秀!