Megjegyzés: Az Application Domain technológia csak .NET Framework keretrendszerek esetén érhető el. .NET Core és .NET 5 alatt ezek nem támogatottak.
A .NET esetén minden alkalmazásunk egy Application domain-be ágyazva fut. Egy .NET alkalmazás folyamata (Process) több ilyen Application domaint is tartalmazhat. Ezek egymástól elszeparálva futnak. Több application domain használata növeli a program stabilitását. Ennek oka egyszerű. Ha az egyik domain-ben történik egy kivétel, ami a domain összeomlásához vezet, az nem jár más domain-ek összeomlásával.
Amikor elindítunk egy .NET programot, akkor az alapértelmezett AD (default application domain) létrejön. Ebből tudunk később domain-eket létrehozni, ha kell. A következő program az AppDomain osztály segítségével bemutatja a jelenlegi domain lekérdezését és egy második domain létrehozását.
using System;
namespace PeldaAppdomain
{
class Program
{
static void Main(string[] args)
{
//jelenlegi App Domain nevének lekérdezése
var currentAppDomain = AppDomain.CurrentDomain;
Console.WriteLine(currentAppDomain.FriendlyName);
//2. App Domain létrehozása
var second = AppDomain.CreateDomain("masodik");
Console.WriteLine(currentAppDomain.FriendlyName);
//2. megszüntetése
AppDomain.Unload(second);
Console.ReadKey();
}
}
}
A program kimenete:
pelda_appdomain.exe
pelda_appdomain.exe
Kód futtatása Application domain-ben
Ahhoz, hogy kódot tudjunk futtatni a nem alapértelmezett application domain-ben, a kódot tartalmazó osztályt a létrehozott domain-en keresztül kell példányosítanunk a CreateInstanceAndUnwrap metótdussal. Ennek az első paramétere a típust tartalmazó szerelvény teljes neve, a második paramétere pedig a típus neve. A metódus egy object típust ad vissza, ami konvertálható a kódot tartalmazó típusra, amin metódus hívással kezdeményezhetjük a kódfuttatást.
A futtatandó kódot tartalmazó osztálynál kitétel, hogy a MarshalByRefObject osztályból öröklődjön. Ha az osztály nem ebből a típusból öröklődik, akkor ugyanúgy az alapértelmezett domain-ben fog futni.
using System;
namespace PeldaAppdomain2
{
public class Code : MarshalByRefObject
{
public void Greet()
{
Console.WriteLine("Hello from App Domain: " + AppDomain.CurrentDomain.FriendlyName);
}
}
class Program
{
static void Main(string[] args)
{
var isolated = AppDomain.CreateDomain("isolated");
Type codeType = typeof(Code);
var peldany = (Code)isolated.CreateInstanceAndUnwrap(codeType.Assembly.FullName, codeType.FullName);
peldany.Greet();
AppDomain.Unload(isolated);
Console.ReadKey();
}
}
}
A program kimenete:
Hello from App domain: isolated
A fenti példában, ha a metódus hibát dobna, akkor az nem propagálódna más domain-ekbe. Ezen kívül az application domain akkor igazán hasznos, ha olyan kódot szeretnénk az alkalmazásunkban futtatni, amit nem mi írtunk.
Jogosultságok korlátozása
Szkriptelt és moduláris alkalmazások esetén, mint amilyen a MEF-et bemutató példa is, kifejezetten hasznos, ha a megbízhatóság szempontjából nem ellenőrizhető forrásból származó kód jogosultságait korlátozzuk. Például megtilthatjuk, hogy a kód fájlokat írjon, vagy, hogy reflection-t használjon.
A jogosultságok korlátozását az alábbi példa mutatja be:
using System;
using System.IO;
using System.Security;
using System.Security.Permissions;
namespace PeldaAppdomain3
{
public class Code : MarshalByRefObject
{
public void Greet()
{
Console.WriteLine("Hello from App Domain: " + AppDomain.CurrentDomain.FriendlyName);
}
public void DoSomething()
{
try
{
var fajlok = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
class Program
{
static void Main(string[] args)
{
var temp = Path.GetTempPath();
PermissionSet permissions = new PermissionSet(PermissionState.None);
permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); //csak managed kód futtatása
permissions.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, temp)); //csak fájlok olvasása
permissions.AddPermission(new ReflectionPermission(PermissionState.None)); //nincs reflection
AppDomain isolated = AppDomain.CreateDomain("isolated",
AppDomain.CurrentDomain.Evidence,
AppDomain.CurrentDomain.SetupInformation,
permissions);
Type codeType = typeof(Code);
var peldany = (Code)isolated.CreateInstanceAndUnwrap(codeType.Assembly.FullName, codeType.FullName);
peldany.Greet();
//A megfelelő jogok hiányában itt kivétel történik
peldany.DoSomething();
AppDomain.Unload(isolated);
Console.ReadKey();
}
}
}
A program kimenete:
Hello from App domain: isolated
System.Security.SecurityException: A következő típusú engedélyre vonatkozó kérelem sikertelen: "System.Security.Permissions.FileIOPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".
a következő helyen: System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
a következő helyen: System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark)
a következő helyen: System.Security.CodeAccessPermission.Demand()
a következő helyen: System.AppDomainSetup.VerifyDir(String dir, Boolean normalize)
a következő helyen: System.AppDomain.get_BaseDirectory()
a következő helyen: pelda_appdomain3.Code.DoSomething()
A sikertelen művelet:
Demand
Az első sikertelen engedély típusa:
System.Security.Permissions.FileIOPermission
A sikertelen szerelvény zónája:
MyComputer
A jogok gyűjtője a PermissionSet osztály, ami IPermission interfészt implementáló jogokat tárol. A különböző jogosultságok a System.Security.Permissions névtérben találhatóak. A fontosabbak a következők:
SecurityPermission– Kód futtathatóságára vonatkozó beállításokFileIOPermission– Fájlok és mappák elérésére vonatkozó beállításokReflectionPermission– Reflection-re vonatkozó beállítások
Ezeken kívül számos jogosultságát tudjuk még korlátozni egy külön domain-ben futó kódnak. A jogosultságok közös jellemzője, hogy az osztályok a Permission szóval végződnek.