C# - 从另一个 AppDomain 中的方法返回值
Posted
技术标签:
【中文标题】C# - 从另一个 AppDomain 中的方法返回值【英文标题】:C# - Returning Value From a Method in Another AppDomain 【发布时间】:2012-09-26 22:17:31 【问题描述】:我有一个场景,我从我的 C# 代码中的操作将 DLL 添加到 GAC。然后我需要对新添加的 DLL 执行 Assembly.Load。但是,由于进程启动时 DLL 不在 GAC 中,因此它返回 null。
所以,我看到代码可以在不同的 AppDomain 中运行,这将导致 GAC 可以在单独的 AppDomain 中使用 DLL。
如何将另一个 AppDomain 中的值返回到我的主线程?
我只想跑:
var type = Assembly.Load(assembly).GetType(className);
让它从另一个 AppDomain 返回到我的主线程。
【问题讨论】:
您是否尝试过使用反射..?例如类型 t = typeof(YourNamespace.YourClass);字符串 assemblyQualifiedName = t.AssemblyQualifiedName;类型类型 = Type.GetType(assemblyQualifiedName, false, true); // 类型不会为空 【参考方案1】:您将不得不对 .NET Remoting 进行一些尝试。您在另一个 AppDomain 上加载的对象需要从 MarshalByRefObject 类 (http://msdn.microsoft.com/en-us/library/system.marshalbyrefobject.aspx) 派生。
为了节省时间,以下是该链接中的代码:
using System;
using System.Reflection;
public class Worker : MarshalByRefObject
public void PrintDomain()
Console.WriteLine("Object is executing in AppDomain \"0\"",
AppDomain.CurrentDomain.FriendlyName);
class Example
public static void Main()
// Create an ordinary instance in the current AppDomain
Worker localWorker = new Worker();
localWorker.PrintDomain();
// Create a new application domain, create an instance
// of Worker in the application domain, and execute code
// there.
AppDomain ad = AppDomain.CreateDomain("New domain");
Worker remoteWorker = (Worker) ad.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName,
"Worker");
remoteWorker.PrintDomain();
/* This code produces output similar to the following:
Object is executing in AppDomain "source.exe"
Object is executing in AppDomain "New domain"
*/
【讨论】:
完美运行。非常感谢。【参考方案2】:一般来说,应用程序域之间共享的对象必须派生自 MarshalByRefObject。如果类型是在动态加载的 DLL 中定义的,则返回实际类型会出现问题。由于该类型在主线程的 AppDomain 中不可用。您可以将其转换为已在主应用程序线程中加载的 DLL 中可用的基类。
我过去所做的是为我想在应用程序域之间共享的类创建一个接口。显然,该接口将位于主应用程序和动态加载的 dll 共享的一些基本 dll 中。
在你的基础 dll 中你可以声明你的接口:
public interface IMyBaseInterface
void DoStuff();
然后在动态加载的dll中,类实现接口并派生自MarshalByRefObject:
public class MyDynamicClass : MarshalByRefObject, IMyBaseInterface
public void DoStuff()
Console.WriteLine("Hello other app domain!");
加载对象实例的代码如下所示:
AppDomainSetup ads = new AppDomainSetup();
AppDomain appDomain = AppDomain.CreateDomain(_appDomainName, null, ads);
IMyBaseInterface myObj = (IMyBaseInterface) appDomain.CreateInstanceAndUnwrap(assemblyName, typeName);
myObj.DoStuff();
【讨论】:
我试图为我的动态创建的实例设置公共属性,该实例已经实现了自定义接口。但是您的回答对我有所帮助,因为现在我只是在接口中调用一个方法并让 dll 本身设置公共属性:) 再次感谢!【参考方案3】:当您通过 AppDomain 边界“泄漏”对象(在您的情况下隐式或显式)时,必须将实现程序集加载到两个域中。
正如您已经注意到的,第一次从 AppDomain 中的程序集向类请求时不在 GAC 中的程序集不会被加载到 AppDomain(事实上它不是 GAC 被缓存到 AppDomain 生命周期结束,因为预计大会不会神奇地出现在 GAC 中)。
我认为您必须将新 GAC 程序集的类保留在新的 AppDomain 中。
【讨论】:
以上是关于C# - 从另一个 AppDomain 中的方法返回值的主要内容,如果未能解决你的问题,请参考以下文章
是否可以从另一个单独的 .NET AppDomain 更改 .NET AppDomain 中的字符串属性的值
C# 在 appdomain 调用方法中加载 dll,而不会再次加载 dll
受限 AppDomain 中的 C# 类继承自位于主 AppDomain 中的其他类