使用 MarshalByRefObject 跨应用程序域传递数据

发布于 2024-08-12 02:06:41 字数 1946 浏览 1 评论 0原文

我在两个 .NET 应用程序域之间传递一些数据时遇到了一些麻烦,我希望这里有人可以帮助我。

基本上我拥有的是一个主应用程序(Main),它将程序集AB加载到它的主域中,然后当我运行插件时( C) Main 调用 B 上的创建域方法,该方法创建一个新域并加载 C 和一个实例B进入其中,这样C只能访问B而不能访问其他。

B 包含一个指向 Main 的 IDispatch 的指针,但似乎只有在使用 C 将其加载到新域中后才能获取它。我想做的是从 B 的新域实例发送指针的副本,并将其发送到仍在默认域中运行的 A

仅供记录,我控制 A、B 和 C,但不控制 Main

抱歉,如果这有点难以理解,我会尽力解释它。

代码:

在 A 中:

public class Tunnel : MarshalByRefObject
{
    public void SetPointer(int dispID)
    {
        IntPtr pointer = new IntPtr(dispID);
    }
}

在 B 中:

//Call by Main after loading plug in but after A.dll is loaded.
public void CreateDomain()
{
  AppDomain maindomain= AppDomain.CurrentDomain;
  tunnel = (Tunnel)maindomain.CreateInstanceAndUnwrap(typeof(Tunnel).FullName,
                                                      typeof(Tunnel).FullName);

   AppDomain domain = base.CreateDomain(friendlyName, securityInfo, appDomainInfo);
   //Load assembly C (plug in) in domain.
   // C uses B so it loads a new instance of B into the domain also at the same time.

  // If I do this here it creates new instance of A but I need to use the one in
  // the main domain.
  //tunnel = (Tunnel)domain.CreateInstanceAndUnwrap(typeof(Tunnel).FullName,
                                                    typeof(Tunnel).FullName);
  tunnel.SetPointer(//Send data from B loaded in new domain.)

}

所以最后看起来像这样:

默认域:

  • Main.dll
  • A.dll
  • B.dll

插件域:

  • B.dll
  • C.dll

I'm having a little trouble passing some data between two .NET appdomains and I'm hoping someone on here can help me.

Basically what I have is a main application (Main) which loads assembly A and B into it's main domain, then when I run a plugin(C) Main calls a create domain method on B which creates a new domain and loads C and a instance of B into it, so that C can only access B and not the others.

B contains a pointer to the IDispatch of Main but only it seems to get it after it is loaded into the new domain with C. What I am trying to do is send a copy of the pointer from the new domain instance of B and send it to A which is still running in the default domain.

Just for the record I control A,B and C but not Main

Sorry if this is a bit hard to understand I tried my best to explain it.

Code:

In A:

public class Tunnel : MarshalByRefObject
{
    public void SetPointer(int dispID)
    {
        IntPtr pointer = new IntPtr(dispID);
    }
}

In B:

//Call by Main after loading plug in but after A.dll is loaded.
public void CreateDomain()
{
  AppDomain maindomain= AppDomain.CurrentDomain;
  tunnel = (Tunnel)maindomain.CreateInstanceAndUnwrap(typeof(Tunnel).FullName,
                                                      typeof(Tunnel).FullName);

   AppDomain domain = base.CreateDomain(friendlyName, securityInfo, appDomainInfo);
   //Load assembly C (plug in) in domain.
   // C uses B so it loads a new instance of B into the domain also at the same time.

  // If I do this here it creates new instance of A but I need to use the one in
  // the main domain.
  //tunnel = (Tunnel)domain.CreateInstanceAndUnwrap(typeof(Tunnel).FullName,
                                                    typeof(Tunnel).FullName);
  tunnel.SetPointer(//Send data from B loaded in new domain.)

}

So at the end it looks something like this:

Default Domain:

  • Main.dll
  • A.dll
  • B.dll

Plug in Domain:

  • B.dll
  • C.dll

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

怪我太投入 2024-08-19 02:06:41

在上面的代码中,您调用

AppDomain.CurrentDomain.CreateInstanceAndUnwrap(...)

这只是在当前域中创建对象的一种迂回方式,就像您刚刚调用构造函数一样。您需要在远程域上调用该方法,即。

AppDomain domain = AppDomain.Create(...)
Tunnel tunnel = (Tunnel)domain.CreateInstanceAndUnwrap(...)

如果您随后调用将在远程对象上运行的tunnel.SetPointer(...)。

In your code above you are calling

AppDomain.CurrentDomain.CreateInstanceAndUnwrap(...)

This is simply a round-about way of creating an object in the current domain, same as if you just called the constructor. You need to call that method on a remote domain, ie.

AppDomain domain = AppDomain.Create(...)
Tunnel tunnel = (Tunnel)domain.CreateInstanceAndUnwrap(...)

If you then call tunnel.SetPointer(...) that will run on the remote object.

小嗷兮 2024-08-19 02:06:41

所以我猜想:

class B : MarshallByRef

这样你只需要在类 A 的域中创建对象:

AppDomain domain = ...
B inst = (B) domain.CreateInstanceAndUnwrap(typeof(B).Assembly.FullName, typeof(B).FullName);
inst.DoPlugin("C");

DoPlugin() 方法将动态加载类型“C”并调用任何合适的方法。

So I guess that:

class B : MarshallByRef

with that you need only create the object in the domain from class A:

AppDomain domain = ...
B inst = (B) domain.CreateInstanceAndUnwrap(typeof(B).Assembly.FullName, typeof(B).FullName);
inst.DoPlugin("C");

The DoPlugin() method will dynamically load type "C" and call whatever methods are appropriate.

缘字诀 2024-08-19 02:06:41

创建“子”域时(特别是在单元测试库下运行),您可能必须跨搜索路径和证据进行复制:

var dom = AppDomain.CreateDomain("NewDomain",
    AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.BaseDirectory,
    AppDomain.CurrentDomain.RelativeSearchPath, false);
try
{
    var tunnel = (MyMarshallByRef)dom.CreateInstanceAndUnwrap(
        typeof(MyMarshallByRef).Assembly.FullName,
        typeof(MyMarshallByRef).FullName);

    tunnel.DoStuff("data");
}
finally
{
    AppDomain.Unload(dom);
}

另请注意 DoStuff 方法的任何参数及其返回的任何类型必须标记为[可序列化]

You may have to copy across search paths and evidence when creating "Child" domains (especially for running under unit test libraries):

var dom = AppDomain.CreateDomain("NewDomain",
    AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.BaseDirectory,
    AppDomain.CurrentDomain.RelativeSearchPath, false);
try
{
    var tunnel = (MyMarshallByRef)dom.CreateInstanceAndUnwrap(
        typeof(MyMarshallByRef).Assembly.FullName,
        typeof(MyMarshallByRef).FullName);

    tunnel.DoStuff("data");
}
finally
{
    AppDomain.Unload(dom);
}

Also note that any arguments the the DoStuff method, and any types it returns must be marked [Serializable]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文