I have a marshalable class that contains a factory method. The factory method can be used to instantiate the class in a test AppDomain. I'm trying to understand whether I can use the class with the using( ... ) dispose pattern.
The principle concern for me is whether the test AppDomain is Unloaded -- and when. I've added a static flag to the class that's set when an instance method is invoked. If the appdomain is not unloaded, then I believe this flag should retain it's setting in subsequent invocations.
A sample class and test console app would look like this:
using System;
using System.Reflection;
using System.Threading;
namespace AppDomainInDispose
{
public class TestClass : MarshalByRefObject, IDisposable
{
public void Run()
{
Console.WriteLine("Hello from {0}", Thread.GetDomain().FriendlyName);
if (_flag)
Console.WriteLine("Flagged!");
else
_flag = true;
}
private static bool _flag = false;
public static TestClass InstantiateInTestDomain()
{
var callingDomain = Thread.GetDomain();
var setup = new AppDomainSetup() { ApplicationBase = callingDomain.SetupInformation.ApplicationBase };
_domain = AppDomain.CreateDomain("test-domain", null, setup);
_domain.DomainUnload += _domain_DomainUnload;
var assembly = Assembly.GetAssembly(typeof(TestClass)).CodeBase;
var proxy = _domain.CreateInstanceFromAndUnwrap(assembly, "AppDomainInDispose.TestClass") as TestClass;
return proxy;
}
static void _domain_DomainUnload(object sender, EventArgs e)
{
Console.WriteLine("Unloading");
}
public static AppDomain _domain = null;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~TestClass()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if(disposing)
{
//AppDomain.Unload(_domain); // can't, as I'm in the AppDomain
}
}
}
class Program
{
static void Main(string[] args)
{
using(var testClass = TestClass.InstantiateInTestDomain())
{
testClass.Run();
}
using (var testClass = TestClass.InstantiateInTestDomain())
{
testClass.Run(); // if the appdomain hasn't been unloaded then the static flag will still be set
}
Console.ReadKey();
}
}
}
It seems that in this limited test the AppDomain is being unloaded -- but I'm not sure where. Could someone explain what's going on with the AppDomain? Is this approach a very bad idea?
EDIT: Looks like you can have multiple AppDomains sharing the same name, which I didn't realise. Also, the DomainUnload event isn't fired, so I might assume that the domain is not being unloaded. That, or the event is not fired in some circumstances (perhaps while the hosting process is shutting down).