名前空間 System
自己紹介
「そなたたちよ、聞くがよい。我は隼のごとき目で全てを見通す力を持つ者なり。AppDomain」とは、.NETで提供されるアプリケーションドメインを管理するクラスである。これを使えば、アプリケーションの実行環境を分離し、信頼性とセキュリティを向上させることが可能だ。アプリケーションの起動パスを取得したり、アセンブリを動的にロード・アンロードする際に活躍する。
基本機能
まずはAppDomainの基本機能を紹介しよう。以下のコードは、現在のアプリケーションの起動パスを取得する方法を示しておる。
using System;
class Program
{
static void Main()
{
// AppDomainで起動パスを取得
string startupPath = AppDomain.CurrentDomain.BaseDirectory;
Console.WriteLine("起動パス: " + startupPath);
}
}
Application.StartupPathとの違いだが、前者はWPFやWindows Formsで使用され、AppDomainはLinuxなどでも使用可能で範囲が広いのだ。
よく使う場面と注意点
AppDomainの最大の強みは、アセンブリを動的にロードし、アンロードできる点にある。例えば、MyAssembly.dllをロードし、関数を呼び出す例を示そう。
// MyClass.cs
namespace MyNamespace
{
public class MyClass
{
public void MyMethod()
{
Console.WriteLine("MyMethod called in MyAssembly.dll");
}
}
}
using System;
using System.Reflection;
class Program
{
static void Main()
{
// 現在のアプリケーションドメインを取得
AppDomain currentDomain = AppDomain.CurrentDomain;
Console.WriteLine("Current AppDomain: " + currentDomain.FriendlyName);
// 新しいアプリケーションドメインを作成
AppDomain newDomain = AppDomain.CreateDomain("NewAppDomain");
Console.WriteLine("New AppDomain: " + newDomain.FriendlyName);
try
{
// 新しいAppDomainでアセンブリをロード
newDomain.Load("MyAssembly");
// 新しいAppDomainでメソッドを呼び出すためのデリゲートを作成
newDomain.DoCallBack(CallMethodInNewDomain);
}
finally
{
// 新しいAppDomainをアンロード
AppDomain.Unload(newDomain);
Console.WriteLine("New AppDomain unloaded.");
}
}
static void CallMethodInNewDomain()
{
// MyAssembly.dllの型を取得
Type type = Type.GetType("MyNamespace.MyClass, MyAssembly");
// パブリックメソッドを取得
MethodInfo method = type.GetMethod("MyMethod");
// インスタンスを作成してメソッドを呼び出し
object obj = Activator.CreateInstance(type);
method.Invoke(obj, null);
}
}
引数付き関数を呼び出す実装例
次は、引数付きの関数を呼び出す場合の例だ。
// MyClass.cs
namespace MyNamespace
{
public class MyClass
{
public void MyMethod(string message)
{
Console.WriteLine($"MyMethod called in MyAssembly.dll with message: {message}");
}
}
}
using System;
using System.Reflection;
class Program
{
static void Main()
{
// 現在のアプリケーションドメインを取得
AppDomain currentDomain = AppDomain.CurrentDomain;
Console.WriteLine("Current AppDomain: " + currentDomain.FriendlyName);
// 新しいアプリケーションドメインを作成
AppDomain newDomain = AppDomain.CreateDomain("NewAppDomain");
Console.WriteLine("New AppDomain: " + newDomain.FriendlyName);
try
{
// 新しいAppDomainでアセンブリをロード
newDomain.Load("MyAssembly");
// 新しいAppDomainでメソッドを呼び出すためのデリゲートを作成
newDomain.DoCallBack(() => CallMethodInNewDomain("Hello from Main AppDomain!"));
}
finally
{
// 新しいAppDomainをアンロード
AppDomain.Unload(newDomain);
Console.WriteLine("New AppDomain unloaded.");
}
}
static void CallMethodInNewDomain(string message)
{
// MyAssembly.dllの型を取得
Type type = Type.GetType("MyNamespace.MyClass, MyAssembly");
// パブリックメソッドを取得
MethodInfo method = type.GetMethod("MyMethod");
// インスタンスを作成してメソッドを呼び出し
object obj = Activator.CreateInstance(type);
method.Invoke(obj, new object[] { message });
}
}
異なるバージョンのアセンブリを同時に使用する
異なるバージョンの同じアセンブリを同時に使用する際、AppDomainはその解決策を提供する。以下は、バージョンの競合を回避するための例だ。
// MyClass1.cs
namespace MyNamespace1
{
public class MyClass
{
public void MyMethod()
{
Console.WriteLine("MyMethod called in MyAssembly1.dll");
}
}
}
// MyClass2.cs
namespace MyNamespace2
{
public class MyClass
{
public void MyMethod()
{
Console.WriteLine("MyMethod called in MyAssembly2.dll");
}
}
}
/app/bin
Program.exe
/bin1
MyAssembly1.dll
/bin2
MyAssembly2.dll
using System;
using System.Reflection;
class Program
{
static void Main()
{
string appBase = AppDomain.CurrentDomain.BaseDirectory;
// AppDomain1を作成
AppDomainSetup setup1 = new AppDomainSetup
{
ApplicationBase = appBase + @"..\bin1"
};
AppDomain domain1 = AppDomain.CreateDomain("Domain1", null, setup1);
// AppDomain2を作成
AppDomainSetup setup2 = new AppDomainSetup
{
ApplicationBase = appBase + @"..\bin2"
};
AppDomain domain2 = AppDomain.CreateDomain("Domain2", null, setup2);
try
{
// AppDomainにアセンブリをロードしてメソッドを呼び出す
domain1.DoCallBack(() => LoadAndCallMethod(appBase + @"..\bin1\MyAssembly1.dll", "MyNamespace1.MyClass", "MyMethod"));
domain2.DoCallBack(() => LoadAndCallMethod(appBase + @"..\bin2\MyAssembly2.dll", "MyNamespace2.MyClass", "MyMethod"));
}
finally
{
// AppDomainのアンロード
AppDomain.Unload(domain1);
AppDomain.Unload(domain2);
}
}
static void LoadAndCallMethod(string assemblyPath, string typeName, string methodName)
{
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type type = assembly.GetType(typeName);
MethodInfo method = type.GetMethod(methodName);
object obj = Activator.CreateInstance(type);
method.Invoke(obj, null);
}
}
まとめとその他のメソッド
AppDomainを使えば、安全性と柔軟性を保ちながら複雑なアセンブリ管理が可能だ。さらに、アセンブリのシャドウコピーや非同期処理など、便利な機能も備えている。
さあ、そなたたちよ、AppDomainの力を得た今、さらなる高みへと飛翔するがよい!
0 件のコメント:
コメントを投稿