需要来自外部供应商的dll的2个静态类副本

时间:2014-08-05 19:51:31

标签: c# .net dll

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

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

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

3 个答案:

答案 0 :(得分:3)

您可以通过AppDomains实现所需。不在AppDomain边界之间共享静态实例。并且您可以编写将订阅来自不同appdomains的事件的代码,但是远程处理存在一些复杂性。有关详细信息,请参阅这些问题和答案:

What is a .NET application domain?

How can I subscribe to an event across AppDomains (object.Event += handler;)

答案 1 :(得分:2)

阅读它。我觉得可以通过将dll加载到两个单独的应用程序域中来完成,这将允许您在每个域中单独实例化该类。据说我从来没有这样做过。

这些问题的代码应该能够产生答案我将尝试创建样本并在今晚进行编辑。

How to use an AppDomain to limit a static class' scope for thread-safe use?

我正在为它编写示例,但发现了一个开箱即用的示例 Static Fields in AppDomain

答案 2 :(得分:2)

两个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();