4

C#コードのアクションからGACにDLLを追加するシナリオがあります。次に、新しく追加されたDLLに対してAssembly.Loadを実行する必要があります。ただし、プロセスの開始時にDLLがGACになかったため、DLLはnullを返します。

したがって、コードを別のAppDomainで実行できることがわかります。これにより、別のAppDomainのGACからDLLを使用できるようになります。

他のAppDomainからメインスレッドに値を返すにはどうすればよいですか?

私は単に実行したい:

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

そして、他のAppDomainからメインスレッドに戻してもらいます。

4

3 に答える 3

10

.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"
 */
于 2012-09-26T22:56:47.160 に答える
5

一般に、アプリ ドメイン間で共有されるオブジェクトは、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(); 
于 2012-09-26T23:03:39.137 に答える
2

AppDomain 境界を介してオブジェクトを「リーク」する場合 (暗黙的に、またはあなたの場合のように明示的に)、実装アセンブリを両方のドメインにロードする必要があります。

既にお気付きのように、AppDomain のアセンブリからのクラスへの最初の要求時に GAC になかったアセンブリは、AppDomain にロードされません (GAC ではないという事実は、AppDomain の有効期間が終了するまでキャッシュされます。アセンブリが魔法のように GAC に表示されることが期待されます)。

その新しいAppDomainで新しくGACされたアセンブリからクラスを保持する必要があると思います。

于 2012-09-26T23:06:09.667 に答える