如何获取父级AppDomain?

4
我需要在C#中做类似以下的事情(伪代码):
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();
}

我有一个不可序列化和不可编组的对象在一个应用程序域中。

我想创建第二个域并执行foo()。在第二个域内,我想在原始域上执行bar()。

如何将原始域传递给子域?

2个回答

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运行时创建的初始域 - 而是我们立即创建的一个域。
您可以查看我博客文章中的注释,了解一种使用app.config让.Net运行时自动为您挂钩此功能的方法。
编辑:我忘记添加我使用的扩展方法,这里它是:
/// <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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接