需要从外部供应商的静态类的2个副本's dll

本文关键字:dll 副本 2个 从外部 供应商 静态类 | 更新日期: 2023-09-27 18:16:26

我们正在使用外部供应商的dll与他们通信,作为我们应用程序的一部分。这个dll有一个静态类,其中包括一些确定用于连接到供应商的帐户(凭据)的属性。但是,我们的应用程序需要根据代码路径使用两个不同的帐户进行连接。这很好(我们只需在每个连接之前设置正确的帐户),但问题是我们还需要将事件处理程序绑定到供应商的事件(也在这个静态类上),并且事件处理程序需要响应为每个帐户触发的事件。拥有静态类的一个副本意味着只有来自当前连接的帐户的事件才会被拾取。

我知道这不是一个好的设计(如果由我来决定,供应商的类将被实例化两次,每个帐户一次),但是我们无法控制供应商如何设计他们的dll,他们也不会改变它。

似乎让事件处理程序监视两个帐户的事件的唯一方法是使用我们的应用程序的两个副本,但这真的很难看。有没有办法以某种方式有两个副本的dll从我们的项目引用?或者有其他解决这个问题的方法吗?

需要从外部供应商的静态类的2个副本's dll

您可以使用AppDomains实现所需的功能。静态实例不能跨AppDomain边界共享。你可以编写代码来订阅来自不同应用域的事件,但是远程操作有些复杂。有关更多信息,请参阅这些问题和答案:

什么是。net应用程序域?

如何跨AppDomains (object)订阅事件?事件+= handler;)

从阅读开始。我觉得可以通过将dll加载到两个单独的应用程序域来完成,这将允许您在每个域中分别实例化类。话虽如此,我从来没有做过这件事。

这个问题有代码,应该能够导致答案,我将尝试创建一个样本和编辑今晚。

如何使用AppDomain来限制静态类'线程安全使用的范围?

我正在写它的例子,但发现一个开箱即用的AppDomain中的静态字段

两个AppDomain想法的一些代码。假设您有静态类Foo .:

public static class Foo {
  public static event EventHandler<EventArgs> Bar;
  public static string Message;
  public static void RunBar() {
    var bar = Bar;
    if (bar != null) {
      bar.Invoke(null, EventArgs.Empty);
    }
  }
}

首先定义接口,包含所有你感兴趣的方法和事件,比如:

public interface IFooWrapper {
  event EventHandler<EventArgs> Bar;
  string Message { get; set; }
  void RunBar();
}

将实现此接口并将调用/事件处理程序委托给静态类Foo的对象。

public class FooWrapper : MarshalByRefObject, IFooWrapper {
  public string Message {
    get { return Foo.Message; }
    set { Foo.Message = value; }
  }
  public event EventHandler<EventArgs> Bar;
  public FooWrapper() {
    Foo.Bar += (sender, args) => {
      var myBar = Bar;
      if (myBar != null) {
        myBar(sender, args);
      }
    };
  }
  public void RunBar() {
    Foo.RunBar();
  }
}

好了,现在可以开始了-创建应用程序域,并在这些应用程序域中实例化FooWrapper,将IFooWrapper引用传递到当前域

  var domain1 = AppDomain.CreateDomain("Foo1");
  var domain2 = AppDomain.CreateDomain("Foo2");
  var foo1 = (IFooWrapper)domain1.CreateInstanceAndUnwrap("ConsoleApplication2", "ConsoleApplication2.FooWrapper");
  foo1.Message = "Foo1";
  foo1.Bar += (sender, eargs) => {
    Console.Out.WriteLine("foo1 bar called");
  };
  var foo2 = (IFooWrapper)domain2.CreateInstanceAndUnwrap("ConsoleApplication2", "ConsoleApplication2.FooWrapper");
  foo2.Message = "Foo2";
  foo2.Bar += (sender, eargs) => {
    Console.Out.WriteLine("foo2 bar called");
  };

现在是一些实际的测试:

// writes Foo1
Console.Out.WriteLine(foo1.Message);
// writes Foo2
Console.Out.WriteLine(foo2.Message);
// writes foo1 bar called
foo1.RunBar();
// writes foo2 bar called
foo2.RunBar();
// does nothing
Foo.RunBar();