2011-08-19 3 views
2

나는 C#을 (의사)에서이 같은 작업을 수행해야합니다부모 AppDomain을 얻는 방법?

static var ns = new Non_Serializable_Nor_Marshal() 

var app = new AppDomain(); 
app.execute(foo) 

void foo() 
{ 
    var host = AppDomain.Current.Parent; //e.g. the original one 
    host.execute(bar) 
} 

void bar() 
{ 
    ns.Something(); 
} 

IOW 내가 하나의 AppDomain에서 비 serializeable도 정렬 화 객체가 있습니다. 두 번째 도메인을 만들고 foo()를 실행하고 싶습니다. 두 번째 도메인 내에서 원래 도메인에서 bar()를 실행하려고합니다.

어떻게 원래 도메인을 하위 도메인으로 전달합니까?

답변

5

은 또한 AppDomainManager를 사용하여 약간의 트릭을 사용할 수 있습니다. 기본적으로 '기본'도메인을 자동으로 모든 도메인에 자동으로 연결할 수 있습니다. 즉, 기본 도메인을 폐기한다는 의미입니다. 여기

모든 마법을 수행하는 클래스입니다 :

/// <summary> 
/// Represents a <see cref="AppDomainManager"/> that is 
/// aware of the primary application AppDomain. 
/// </summary> 
public class PrimaryAppDomainManager : AppDomainManager 
{ 
    private static AppDomain _primaryDomain; 

    /// <summary> 
    /// Gets the primary domain. 
    /// </summary> 
    /// <value>The primary domain.</value> 
    public static AppDomain PrimaryDomain 
    { 
     get 
     { 
      return _primaryDomain; 
     } 
    } 

    /// <summary> 
    /// Sets the primary domain. 
    /// </summary> 
    /// <param name="primaryDomain">The primary domain.</param> 
    private void SetPrimaryDomain(AppDomain primaryDomain) 
    { 
     _primaryDomain = primaryDomain; 
    } 

    /// <summary> 
    /// Sets the primary domain to self. 
    /// </summary> 
    private void SetPrimaryDomainToSelf() 
    { 
     _primaryDomain = AppDomain.CurrentDomain; 
    } 

    /// <summary> 
    /// Determines whether this is the primary domain. 
    /// </summary> 
    /// <value> 
    ///  <see langword="true"/> if this instance is the primary domain; otherwise, <see langword="false"/>. 
    /// </value> 
    public static bool IsPrimaryDomain 
    { 
     get 
     { 
      return _primaryDomain == AppDomain.CurrentDomain; 
     } 
    } 

    /// <summary> 
    /// Creates the initial domain. 
    /// </summary> 
    /// <param name="friendlyName">Name of the friendly.</param> 
    /// <param name="securityInfo">The security info.</param> 
    /// <param name="appDomainInfo">The AppDomain setup info.</param> 
    /// <returns></returns> 
    public static AppDomain CreateInitialDomain(string friendlyName, Evidence securityInfo, AppDomainSetup appDomainInfo) 
    { 
     if (AppDomain.CurrentDomain.DomainManager is PrimaryAppDomainManager) 
      return null; 

     appDomainInfo = appDomainInfo ?? new AppDomainSetup(); 
     appDomainInfo.AppDomainManagerAssembly = typeof(PrimaryAppDomainManager).Assembly.FullName; 
     appDomainInfo.AppDomainManagerType = typeof(PrimaryAppDomainManager).FullName; 

     var appDomain = AppDomainManager.CreateDomainHelper(friendlyName, securityInfo, appDomainInfo); 
     ((PrimaryAppDomainManager)appDomain.DomainManager).SetPrimaryDomainToSelf(); 
     _primaryDomain = appDomain; 
     return appDomain; 
    } 

    /// <summary> 
    /// Returns a new or existing application domain. 
    /// </summary> 
    /// <param name="friendlyName">The friendly name of the domain.</param> 
    /// <param name="securityInfo">An object that contains evidence mapped through the security policy to establish a top-of-stack permission set.</param> 
    /// <param name="appDomainInfo">An object that contains application domain initialization information.</param> 
    /// <returns>A new or existing application domain.</returns> 
    /// <PermissionSet> 
    ///  <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="ControlEvidence, ControlAppDomain, Infrastructure"/> 
    /// </PermissionSet> 
    public override AppDomain CreateDomain(string friendlyName, Evidence securityInfo, AppDomainSetup appDomainInfo) 
    { 
     appDomainInfo = appDomainInfo ?? new AppDomainSetup(); 
     appDomainInfo.AppDomainManagerAssembly = typeof(PrimaryAppDomainManager).Assembly.FullName; 
     appDomainInfo.AppDomainManagerType = typeof(PrimaryAppDomainManager).FullName; 

     var appDomain = base.CreateDomain(friendlyName, securityInfo, appDomainInfo); 
     ((PrimaryAppDomainManager)appDomain.DomainManager).SetPrimaryDomain(_primaryDomain); 

     return appDomain; 
    } 
} 

그리고 당신은 약간 Main() (응용 프로그램 항목)을 변경해야 : 당신이 PrimaryAppDomainManager.PrimaryDomain를 얻을 수

/// <summary> 
/// The main entry point for the application. 
/// </summary> 
static void Main(string[] args) 
{ 
    new Program().Run(args); 
} 

void Run(string[] args) 
{ 
    var domain = PrimaryAppDomainManager.CreateInitialDomain("PrimaryDomain", null, null); 
    if (domain == null) 
    { 
     // Original Main() code here. 
    } 
    else 
    { 
     domain.CreateInstanceAndUnwrap<Program>().Run(args); 
    } 
} 

을 이제 어느 시점에 기본 도메인에 대한 참조를 얻으십시오. 닷넷 런타임에 의해 생성 된 inital 도메인이 아니라는 것을 기억하십시오.

blog post에있는 주석을 보면 .Net 런타임에서 app.config를 자동으로 사용하기위한 방법을 찾을 수 있습니다.

편집 : 내가 사용하는 확장 메서드를 추가하는 것을 잊었다, 여기있다 :

/// <summary> 
/// Creates a new instance of the specified type. 
/// </summary> 
/// <typeparam name="T">The type of object to create.</typeparam> 
/// <param name="appDomain">The app domain.</param> 
/// <returns>A proxy for the new object.</returns> 
public static T CreateInstanceAndUnwrap<T>(this AppDomain appDomain) 
{ 
    var res = (T)appDomain.CreateInstanceAndUnwrap(typeof(T)); 
    return res; 
} 
0

mscoree를 참조한 다음 해당 메서드를 사용해 볼 수 있습니다. 나는 이것을 나의 프로젝트 중 하나에서 사용했다. mscoree는 입력없이 AppDomains를 추적합니다. 당신이 상호 운용성 사용하지 않을 경우 (http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx에서 적응)

/// <summary> 
    /// Returns the primary application domain. 
    /// </summary> 
    /// <returns>The primary application domain.</returns> 
    public static AppDomain GetPrimaryAppDomain() 
    { 
     return GetAppDomain(Process.GetCurrentProcess().MainModule.ModuleName); 
    } 

    /// <summary> 
    /// Returns the application domain with the given friendly name. 
    /// </summary> 
    /// <param name="friendlyName">The friendly name of the application domain.</param> 
    /// <returns>The application domain with the given friendly name.</returns> 
    /// <exception cref="System.ArgumentNullException">Thrown if friendlyName is null.</exception> 
    public static AppDomain GetAppDomain(string friendlyName) 
    { 
     if (friendlyName == null) 
     { 
      throw new ArgumentNullException("friendlyName"); 
     } 
     IntPtr handle = IntPtr.Zero; 
     CorRuntimeHostClass host = new CorRuntimeHostClass(); 
     try 
     { 
      host.EnumDomains(out handle); 
      object domain = null; 
      while (true) 
      { 
       host.NextDomain(handle, out domain); 
       if (domain == null) 
       { 
        return null; 
       } 
       AppDomain appDomain = (AppDomain)domain; 
       if (appDomain.FriendlyName == friendlyName) 
       { 
        return appDomain; 
       } 
      } 
     } 
     finally 
     { 
      host.CloseEnum(handle); 
      Marshal.ReleaseComObject(host); 
      host = null; 
     } 
    } 

관련 문제