잊지 않겠습니다.

먼저, AppDomain을 이용한 개발을 하는 가장 큰 장점은 Process보다 더 가벼운 단위로의 동작이 가능하고, Programming 적으로 동작이 가능하다는 장점을 가지고 있다. 그렇지만, 이러한 동작 및 Resource의 제어를 하기 위해서 모든 AppDomain를 제어하고, Process당 하나만 존재하는 진정한 Singleton object가 필요하게 된다.

이 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;
            }
        }
    }
}


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();
}
}

Posted by Y2K
,