2012-09-26 32 views
2

我有一个场景,我将C#代码中的动作添加到GAC中。然后我需要在新添加的DLL上执行Assembly.Load。但是,由于进程启动时该DLL不在GAC中,因此它将返回空值。C# - 从另一个AppDomain中的方法返回值

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

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

我只是想运行:

变种类型= Assembly.Load(组装).GetType(类名);

并让它从另一个AppDomain返回到我的主线程。

在此先感谢。

+0

你有没有尝试过使用反射..?例如 类型t = typeof(YourNamespace.YourClass); string assemblyQualifiedName = t。AssemblyQualifiedName; Type type = Type.GetType(assemblyQualifiedName,false,true); //类型不为空 – MethodMan

回答

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" 
*/ 
+0

完美工作。非常感谢。 –

4

被应用程序域之间共享必须从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(); 
+1

+1使用接口 – Fabio

+0

我试图为我已经实现了自定义接口的动态创建的实例设置公共属性。但是你的答案帮助了我,因为现在我只是在Interface中调用一个方法,并让dll自己设置公共属性:)再次感谢! –

1

当您“泄漏“通过AppDomain边界的对象(隐式地,或者像你的情况那样显式)实现程序集必须加载到两个域中。

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

我想你必须在新的AppDomain中保留新GAC'ed程序集中的类。

相关问题