먼저, AppDomain을 이용한 개발을 하는 가장 큰 장점은 Process보다 더 가벼운 단위로의 동작이 가능하고, Programming 적으로 동작이 가능하다는 장점을 가지고 있다. 그렇지만, 이러한 동작 및 Resource의 제어를 하기 위해서 모든 AppDomain를 제어하고, Process당 하나만 존재하는 진정한 Singleton object가 필요하게 된다.
이 Singleton object를 만들기 위한 컨셉은 다음과 같다.
Generic으로 만들어져있기 때문에, 사용될 constraint class의 경우에도 MarsharByObject class를 상속받거나 Serializable 속성을 가져야지 된다.
사용은 다음과 같다.
이 Singleton object를 만들기 위한 컨셉은 다음과 같다.
Singleton object가 동작할 working AppDomain의 지정
using System;
using System.Runtime.InteropServices;
namespace ProxyServerForMsn.AppDomainManager
{
public class CrossAppDomainSingleton<T> : MarshalByRefObject where T : new()
{
private const string AppDomainName = "Singleton AppDomain";
// Singleton Working AppDomain 지정
private static T instance;
public static void ListupAppDomains()
{
IntPtr enumHandle = IntPtr.Zero;
mscoree.CorRuntimeHostClass host = new mscoree.CorRuntimeHostClass();
try
{
host.EnumDomains(out enumHandle);
object domain = null;
while(true)
{
host.NextDomain(enumHandle, out domain);
if(domain == null)
{
break;
}
AppDomain appDomain = domain as AppDomain;
if(appDomain != null)
{
Console.WriteLine(appDomain.FriendlyName);
}
}
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
host = null;
}
}
private static AppDomain GetAppDomain(string friendlyName)
{
IntPtr enumHandle = IntPtr.Zero;
mscoree.CorRuntimeHostClass host = new mscoree.CorRuntimeHostClass();
try
{
host.EnumDomains(out enumHandle);
object domain = null;
while(true)
{
host.NextDomain(enumHandle, out domain);
if(domain == null)
{
break;
}
AppDomain appDomain = (AppDomain)domain;
if(appDomain.FriendlyName.Equals(friendlyName))
{
return appDomain;
}
}
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
host = null;
}
return null;
}
public static T Instance
{
get
{
if (null == instance)
{
AppDomain appDomain = GetAppDomain(AppDomainName);
if (null == appDomain)
{
appDomain = AppDomain.CreateDomain(AppDomainName);
}
Type type = typeof (T);
T createInstance = (T) appDomain.GetData(type.FullName);
if (null == createInstance)
{
createInstance =
(T) appDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
appDomain.SetData(type.FullName, createInstance);
}
instance = createInstance;
}
return instance;
}
}
}
}
using System.Runtime.InteropServices;
namespace ProxyServerForMsn.AppDomainManager
{
public class CrossAppDomainSingleton<T> : MarshalByRefObject where T : new()
{
private const string AppDomainName = "Singleton AppDomain";
// Singleton Working AppDomain 지정
private static T instance;
public static void ListupAppDomains()
{
IntPtr enumHandle = IntPtr.Zero;
mscoree.CorRuntimeHostClass host = new mscoree.CorRuntimeHostClass();
try
{
host.EnumDomains(out enumHandle);
object domain = null;
while(true)
{
host.NextDomain(enumHandle, out domain);
if(domain == null)
{
break;
}
AppDomain appDomain = domain as AppDomain;
if(appDomain != null)
{
Console.WriteLine(appDomain.FriendlyName);
}
}
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
host = null;
}
}
private static AppDomain GetAppDomain(string friendlyName)
{
IntPtr enumHandle = IntPtr.Zero;
mscoree.CorRuntimeHostClass host = new mscoree.CorRuntimeHostClass();
try
{
host.EnumDomains(out enumHandle);
object domain = null;
while(true)
{
host.NextDomain(enumHandle, out domain);
if(domain == null)
{
break;
}
AppDomain appDomain = (AppDomain)domain;
if(appDomain.FriendlyName.Equals(friendlyName))
{
return appDomain;
}
}
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
host = null;
}
return null;
}
public static T Instance
{
get
{
if (null == instance)
{
AppDomain appDomain = GetAppDomain(AppDomainName);
if (null == appDomain)
{
appDomain = AppDomain.CreateDomain(AppDomainName);
}
Type type = typeof (T);
T createInstance = (T) appDomain.GetData(type.FullName);
if (null == createInstance)
{
createInstance =
(T) appDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
appDomain.SetData(type.FullName, createInstance);
}
instance = createInstance;
}
return instance;
}
}
}
}
Generic으로 만들어져있기 때문에, 사용될 constraint class의 경우에도 MarsharByObject class를 상속받거나 Serializable 속성을 가져야지 된다.
사용은 다음과 같다.
[Serializable]
public class CrossAppHello
{
public void ConsoleOut()
{
Console.WriteLine("Hello World");
}
}
class Program
{
public static void Main()
{
CrossAppDomainSingleton<CrossAppHello>.Instance.ConsoleOut();
}
}
public class CrossAppHello
{
public void ConsoleOut()
{
Console.WriteLine("Hello World");
}
}
class Program
{
public static void Main()
{
CrossAppDomainSingleton<CrossAppHello>.Instance.ConsoleOut();
}
}