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.