C# - 从另一个AppDomain中的方法返回值

时间:2012-09-26 22:17:31

标签: c# appdomain

我有一个场景,我在C#代码中的操作中将DLL添加到GAC。然后我需要对新添加的DLL执行Assembly.Load。但是,由于进程启动时DLL不在GAC中,因此返回null。

因此,我发现代码可以在不同的AppDomain中运行,这将导致DLL在单独的AppDomain中从GAC获得。

如何将其他AppDomain中的值返回到我的主线程?

我只是想跑:

var type = Assembly.Load(assembly).GetType(className);

让它从其他AppDomain返回到我的主线程。

提前致谢。

3 个答案:

答案 0 :(得分:5)

你必须使用.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"
 */

答案 1 :(得分:4)

一般而言,应用域之间共享的对象必须来自MarshalByRefObject。如果在动态加载的DLL中定义了类型,则返回实际类型会有问题。由于您的主线程的AppDomain中没有该类型。您可以将它强制转换为已在主应用程序线程中加载的DLL中可用的基类。

我过去所做的是为我想在app域之间共享的类创建一个界面。显然,接口将位于主应用程序和动态加载的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(); 

答案 2 :(得分:1)

当您通过AppDomain边界“泄漏”对象时(隐式或显式地如您所示),必须将实现程序集加载到两个域中。

正如您已经注意到,在AppACmain中对程序集中的某个类的第一次请求时,不在GAC中的部分将不会加载到AppDomain(事实上它不是GAC被缓存直到AppDomain生命周期结束不希望汇编神奇地出现在GAC中。)

我认为你必须在新的AppDomain中保留新GAC组装的类。