私の目標は、特定のアセンブリを使用する「コードの一部」を、そのアセンブリの複数のバージョンで実行することです。私がこれを行う方法は、アセンブリバージョンごとに1つずつ、別々のAppDomainでその「コードの一部」を実行することです。
これは、「コードの一部」がリフレクションを介してアセンブリを使用する場合にのみ実行できましたが、その「コードの一部」を強く型付けされた方法で記述してもらいたいと思います。
つまり、次のアセンブリがあるとします。
namespace ClassLibrary1
{
public class Class1
{
internal const string Version = "1.0.0.0";
public string Method1() { return Version; }
}
}
また、AssemblyInfo.csには次の定義があります。
[assembly: AssemblyVersion(ClassLibrary1.Class1.Version)]
ここで、「Versions」フォルダがあり、その中にそのアセンブリの複数のバージョンがあるとします。次に例を示します。
/Versions/
├─ /1000/
│ └─ ClassLibrary1.dll
├─ /1001/
│ └─ ClassLibrary1.dll
└─ /1002/
└─ ClassLibrary1.dll
ここで「コードの一部」を実行するために、次のコンソールアプリケーションを使用しています。
class Program
{
static void PieceOfCode(Assembly assembly)
{
Type class1Type = assembly.GetType("ClassLibrary1.Class1");
dynamic class1 = Activator.CreateInstance(class1Type);
string vesion = class1.Method1();
Console.WriteLine(vesion);
}
public sealed class SeparateDomainExecutor : MarshalByRefObject
{
public void Execute(Action<Assembly> action, string assemblyPath)
{
action(Assembly.LoadFrom(assemblyPath));
}
}
static void Main(string[] args)
{
foreach (string file in Directory.EnumerateFiles(@"C:\Versions", "*.dll", SearchOption.AllDirectories))
{
AppDomain domain = AppDomain.CreateDomain("ClassLibrary1 Domain");
var type = typeof(SeparateDomainExecutor);
var runner = (SeparateDomainExecutor)domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
runner.Execute(PieceOfCode, file);
AppDomain.Unload(domain);
}
Console.Read();
}
}
コンソールアプリケーションは正常に動作しますが、「PieceOfCode」でのリフレクションの使用法を次のようなものに置き換えたいと思います。
static void PieceOfCode()
{
ClassLibrary1.Class1 class1 = new ClassLibrary1.Class1();
Console.WriteLine(class1.Method1());
}
これは可能ですか?
私がこれに関して抱えている問題は、PieceOfCodeがClassLibrary1の特定のバージョン(おそらく最新)を使用して記述され、別のAppDomainでそのバージョンを「オーバーライド」する方法がわからないことです。いくつか試しましたが、常にFileLoadExceptionが発生します。
残念ながらClassLibrary1.Class1
、静的に型指定されたコードを記述する場合、アセンブリ参照が必要であり、コンパイラーはその参照を使用して、クラスの特定のバージョンに名前を付けます。完全修飾名(typeof(Class1).AssemblyQualifiedName
)にはアセンブリのパスやファイル名は含まれず、アセンブリ名とバージョンのみが含まれますが、クラスローダーにはさらに制限があります。
使用方法Assembly.LoadFrom(...)
と動的バインディングは、私が思いついた最高のものです。そしてこれは、Officeアセンブリのさまざまなバージョンが、それらを統合するアプリケーションから通常どのように扱われるかです。
私が見る唯一の可能な解決策は、コードの一部を別々のアセンブリ(たとえば、MyStaticIntegration.dll)に分割し、依存関係の各バージョン(ClassLibrary1.dll)に対して個別にコンパイルしてから、MyStaticIntegration.dllの各バージョンをアプリケーションに統合することです。以前にClassLibrary1.dllで行ったのと同じ方法です。
同じ動的な壁がアプリケーションに残りますが、このトリックを使用して動的に使用しているインターフェイスを絞り込むことができます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加