Reputation: 10014
We are using an external vendor's dll to communicate with them as part of our application. This dll has a static class, which includes some properties that determine the account (credentials) that is used to connect to the vendor. However, our application needs to connect using two different accounts depending on the code path. This would be fine (we would just set the correct account right before each connection), but the problem is that we also need to have event handlers tied to the vendor's events (which are also on this static class) and the event handlers need to respond to events fired for each account. Having one copy of the static class means that only events from the currently connected account get picked up.
I know this is not a good design (if it were up to me, the vendor's class would be instantiated twice, once for each account), but we don't have control over how the vendor designed their dll and they are not going to change it.
It seems like the only way to have event handlers watch for events for both accounts is to have two copies of our application, but that's really ugly. Is there any way to somehow have two copies of the dll referenced from our project? Or any other way to solve this issue?
Upvotes: 4
Views: 142
Reputation: 22094
Some code for the two AppDomain idea. Assuming you have static class 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);
}
}
}
So first you define interface with all methods and events in which you're interested like:
public interface IFooWrapper {
event EventHandler<EventArgs> Bar;
string Message { get; set; }
void RunBar();
}
And object that will implement this interface and delegate the calls/event handlers to static class 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();
}
}
Ok so now you're good to go - create app domains, and instantiate FooWrapper
in those app domains, passing to your current domain reference to 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");
};
Now some actual tests:
// 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();
Upvotes: 2
Reputation: 334
From reading it. I Feel like it could be done by loading the dll into two separate app domains which would allow you to instantiate the class separately in each domain. With that said I have never done it.
This questions has code that should be able to lead to answers I will try to create a sample and edit tonight.
How to use an AppDomain to limit a static class' scope for thread-safe use?
I was writing the example for it but found one that works out of the box Static Fields in AppDomain
Upvotes: 2
Reputation: 1658
You may be able to achieve what you need with AppDomains. Static instances are not shared across AppDomain boundaries. And you can write code that will subscribe to events from different appdomains but there are some complications with remoting. See those questions and answers for more info:
What is a .NET application domain?
How can I subscribe to an event across AppDomains (object.Event += handler;)
Upvotes: 3