[英]How to get parent AppDomain?
I need to do something like this in c# (pseudo): 我需要在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();
}
IOW I have a non serializeable nor marshal object in one appdomain. 我在一个应用程序域中有一个非序列化或编组对象。 I want to create a second domain and execute foo().
我想创建第二个域并执行foo()。 From within that second domain I want to execute bar() on the original domain.
从第二个域内我想在原始域上执行bar()。
How do I pass the original domain to the child one? 如何将原始域名传递给孩子?
If you don't want to use interop, you can also use a little trick using AppDomainManager. 如果您不想使用互操作,您还可以使用AppDomainManager使用一个小技巧。 You can basically automatically 'wire' the 'primary' domain into any domains automatically - albiet the way I do it means you discard your real primary domain.
您基本上可以自动将“主要”域“自动”连接到任何域中 - 与我这样做相同意味着您放弃了真正的主域。
Here is the class that does all the magic: 这是完成所有魔术的课程:
/// <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;
}
}
And you need to alter your Main()
(application entry) slightly: 你需要稍微改变你的
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);
}
}
Now at any point you can get PrimaryAppDomainManager.PrimaryDomain
to get a reference to the primary domain, just remember that it isn't the inital domain created by the .Net runtime - it's one we create immediately. 现在,您可以随时获取
PrimaryAppDomainManager.PrimaryDomain
以获取对主域的引用,只需记住它不是.Net运行时创建的初始域 - 它是我们立即创建的域。
You can look at the comments in my blog post for an way to get the .Net runtime to hook this in for you automatically using the app.config. 您可以查看我的博客文章中的注释,了解如何让.Net运行时自动使用app.config将其挂钩。
Edit: I forgot to add the extension method I use, here it is: 编辑:我忘了添加我使用的扩展方法,这里是:
/// <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;
}
You could try referencing mscoree and then using its methods. 您可以尝试引用mscoree然后使用其方法。 I have used this in one of my projects.
我在我的一个项目中使用过它。 mscoree will keep track of your AppDomains without any input.
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;
}
}
(Adapted from http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx ) (改编自http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.