2012-09-26 65 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程序集中的類。

相關問題