2011-08-19 57 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的非可序列化,也没有元帅对象。 我想创建第二个域并执行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()(应用程序入口):在任何时候

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

现在,你可以得到PrimaryAppDomainManager.PrimaryDomain到获得对主域的引用,请记住它不是由.Net运行时创建的初始域 - 它是我们立即创建的域。

您可以查看我的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会在没有任何输入的情况下跟踪您的AppDomain。

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

(从http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx改编)