2011-08-19 2 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 я иметь не serializeable ни объект маршала в одном AppDomain. Я хочу создать второй домен и выполнить foo(). Из этого второго домена я хочу выполнить bar() в исходном домене.

Как передать исходный домен дочернему?

ответ

5

Если вы не хотите использовать Interop, вы можете также использовать небольшой трюк с использованием AppDomainManager. Вы можете автоматически автоматически «перенести» первичный домен в любые домены автоматически - albiet, как я это делаю, означает, что вы отбрасываете свой реальный основной домен.

Вот класс, который делает все волшебство:

/// <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 runtime, чтобы подключить это для автоматического использования app.config.

Edit: Я забыл добавить метод расширения я использую, здесь:

/// <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 без ввода.

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

Смежные вопросы