V minulΘm dφlu povφdßnφ o prost°edφ .NET Framework jsme se zab²vali tφm, Φemu se anglicky °φkß assembly; v ΦeskΘ literatu°e uvidφte vedle Üpatn∞ sklo≥ovatelnΘho äassemblyô termφny äkompletô, äseskupenφô nebo äsestavenφô; jß zde budu pou₧φvat seskupenφ.
Seskupenφ existujφ ve dvou variantßch û soukromß a sdφlenß. Nejprve se budeme zab²vat soukrom²mi seskupenφmi. Ta jsou souΦßstφ jedinΘ aplikace a typicky se instalujφ do domovskΘho adresß°e aplikace. (O dalÜφch mo₧n²ch umφst∞nφch si povφme pozd∞ji.)
Poznamenejme, ₧e vÜechny p°φklady v tomto Φlßnku budou v jazyce C# a budeme je p°eklßdat pomocφ samostatnΘho p°ekladaΦe csc.exe , kter² je souΦßstφ instalace SDK pro platformu .NET. Tento p°ekladaΦ toti₧ poskytuje vφce mo₧nostφ ne₧ r∙znß v²vojovß prost°edφ.
╚tenß°∙m, kterΘ iritujφ hßΦky a Φßrky v identifikßtorech, se omlouvßm, ale jazyk C# a mezijazyk IL je podporujφ, a proto je pou₧φvßm. Kdy₧ u₧ nic jinΘho, v²klad je pro mne pak podstatn∞ snazÜφ.
Seskupenφ vznikne û jakΘ p°ekvapenφ û p°ekladem zdrojovΘho k≤du. Pochopiteln∞ tomu slou₧φ p°ekladaΦ csc.exe , za jist²ch okolnostφ budeme ale vyu₧φvat i linker al.exe a n∞kterΘ z dalÜφch nßstroj∙, jejich₧ p°ehled najdete v minulΘm dφlu tohoto Φlßnku.
Seskupenφ je, jak u₧ vφme, bu∩ spustiteln² soubor (. exe ) nebo dynamickß knihovna (. dll ). Typicky je seskupenφ tvo°eno jedin²m souborem, kter² obsahuje n∞kolik datov²ch typ∙ (tedy t°φd û nezapomφnejme, ₧e seskupenφ obsahuje k≤d v mezijazyku IL, kter² je Φist∞ objektov²). Pozd∞ji uvidφme, ₧e se m∙₧e sklßdat i z n∞kolika soubor∙.
ZaΦneme tφm, ₧e si ukß₧eme jednoduch² p°φklad. Mßme dva zdrojovΘ soubory v jazyce C#:
// Soubor PoΦty.cs
using System;public class PoΦty
{
/// <summary>
/// PoΦφtß faktorißl danΘho celΘho Φφsla
/// </summary>
public static int f(int n)
{if (n<0)
throw new ArgumentException("Zßporn² parametr");
int s = 1;
while(n > 1)s *= n--;
return s;}
}
// Soubor Program.cs
using System;class Program
{public static void Main()
{Console.WriteLine("Zadej Φφslo: ");
string s = Console.ReadLine();
int n = System.Int32.Parse(s);
System.Console.WriteLine("Faktorißl je " + PoΦty.f(n));}
}
Jestli₧e tento program p°elo₧φme p°φkazem
csc Program.cs PoΦty.cs
vytvo°φ se jedinΘ seskupenφ obsahujφcφ t°φdy z obou zdrojov²ch soubor∙ a tzv. manifest. Toto seskupenφ se bude jmenovat Program.exe , jmΘno v²slednΘho seskupenφ lze ale zm∞nit p°epφnaΦem /out: v p°φkazovΘ °ßdce p°ekladaΦe. (P°ipome≥me si, ₧e manifest je soubor obsahujφcφ metadata o celΘm seskupenφ, tj. o tom, jakΘ typy obsahuje, s jak²mi jin²mi seskupenφmi spolupracuje atd.)
Podφvejme se nynφ na vytvo°enΘ seskupenφ podrobn∞ji. Pou₧ijeme k tomu program ildasm.exe , co₧ je disasembler s grafick²m rozhranφm. Po spuÜt∞nφ uvidφte okno jako na obr. 1.
Obr. 1 Program ILDASM ukazuje, ₧e naÜe seskupenφ obsahuje manifest a dv∞ t°φdy
Dvojklik na polo₧ku Manifest otev°e dalÜφ okno, v n∞m₧ m∙₧eme zjistit n∞kterΘ ·daje o tomto seskupenφ.
Obr. 2 Zßkladnφ informace o seskupenφ
Prvnφ polo₧ka °φkß, ₧e naÜe seskupenφ obsahuje odkaz na externφ seskupenφ mscorlib û to je zßkladnφ knihovna prost°edφ .NET. Dßle si zde m∙₧eme p°eΦφst Φφslo po₧adovanΘ verze a token ve°ejnΘho klφΦe û o tom budeme hovo°it pozd∞ji. (VÜimn∞te si, ₧e zßvislΘ seskupenφ obsahujue ·daje o seskupenφ, na n∞m₧ zßvisφ û jmΘno, Φφslo verze a jak²si dalÜφ ·daj. Pokud se tyto ·daje nebudou shodovat, prost°edφ .NET po₧adovanΘ seskupenφ nenajde.)
Nßsleduje popis aktußlnφho seskupenφ jmΘnem Program . V n∞m najdeme Φφslo verze 0.0.0.0 (jde o soukromΘ seskupenφ, kterΘ vlastn∞ nemß Φφslo verze) a odkaz na heÜovacφ algoritmus; o tom se takΘ zmφnφme pozd∞ji.
Vra¥me se do zßkladnφho okna programu ILDASM. Kliknutφm na k°φ₧ek u jmΘna t°φdy p°φsliÜn² uzel stromu rozvineme a dostaneme p°ehled metod. Budou tam i konstruktory, kterΘ si p°ekladaΦ vytvo°il sßm. Dvojklikem na ikonu u jmΘna metody otev°eme dalÜφ okno, v n∞m₧ uvidφme p°eklad metody do IL (obr. 3).
Obr. 3 P°eklad metody do IL
Vra¥me se op∞t k problΘmu, jak vytvo°it soukromΘ seskupenφ. P°φkazem
csc /t:library PoΦty.cs
vytvo°φme seskupenφ PoΦty.dll (dynamickou knihovnu pro .NET) obsahujφcφ pouze t°φdu PoΦty a manifest.
P°φkazem
csc /r:PoΦty.dll Program.cs
vytvo°φme seskupenφ obsahujφcφ t°φdu Program a odkazujφcφ na danou dynamickou knihovnu. (P°epφnaΦ /r: uvßdφ odkaz û referenci û na jinΘ seskupenφ.) Pokud umφstφme dynamickou knihovnu do tΘho₧ adresß°e jako spustiteln² program, bude vÜe v po°ßdku.
Nynφ tedy mßme program, kter² d∞lß totΘ₧ co p°edchozφ verze, ale sklßdß se ze dvou seskupenφ. Tφm jsme zφskali cosi navφc û dynamickou knihovnu lze pou₧φt i v jin²ch programech. Cena je takΘ z°ejmß: Dynamickou knihovnu bude t°eba zavΘst do pam∞ti za b∞hu programu, a to m∙₧e znamenat zpomalenφ programu.
Vra¥me se ale k seskupenφm. P°φkazem
csc /t:module PoΦty.cs
vytvo°φme modul (obdobu souboru . obj pro platformu .NET). Modul nep°edstavuje seskupenφ, obsahuje pouze IL, nikoli vÜak manifest. Modul lze p°ipojit k seskupenφ p°φkazem:
csc /addmodule:PoΦty.netmodule Program.cs
POZOR: Soubor PoΦty.netmodule se sice stane souΦßstφ seskupenφ Program.exe , z∙stane vÜak samostatn², tak₧e seskupenφ se bude sklßdat ze soubor∙ Program.exe a PoΦty.netmodule . Soubor Program.exe bude obsahovat t°φdu Program , manifest a odkaz na soubor PoΦty.netmodule .
Poznamenejme, ₧e pon∞kud dlouhß p°φpona .netmodule nenφ povinnß; pomocφ parametru /out: v p°φkazovΘ °ßdce lze p°edepsat jinou p°φponu. Pou₧φvß se nap°. .net . My vÜak v tomto Φlßnku z∙staneme u p°φpony .netmodule .
P°φkazem
csc /addmodule:poΦty.netmodule /t:module Program.cs
vytvo°φme modul i ze souboru Program.cs; tento modul bude obsahovat t°φdu Program a manifest. Seskupenφ z t∞chto dvou modul∙ vytvo°φme pomocφ linkeru al.exe p°φkazem
al /t:exe /out:prog.exe /main:Program.Main Program.netmodule PoΦty.netmodule
V²sledkem bude seskupenφ slo₧enΘ ze t°φ soubor∙: PoΦty.netmodule , Program.netmodule a prog.exe . Soubor .exe bude obsahovat pouze manifest. Poznamenejme, ₧e volbu /out , specifikujφcφ jmΘno spustitelnΘho souboru, stejn∞ jako volbu /main , udßvajφcφ jmΘno vstupnφho bodu programu, musφme uvΘst.
U₧ vφme, ₧e pokud jedno seskupenφ (nap°. spustiteln² soubor) odkazuje na jinΘ seskupenφ (nap°. dynamickou knihovnu), hledß ho prost°edφ .NET nejprve v domovskΘm adresß°i aplikace. Pokud ho tam nenajde, bude ho hledat v podadresß°i domovskΘho adresß°e aplikace, kter² se bude jmenovat stejn∞ jako hledanΘ seskupenφ.
Vrßtφme se k programu z p°edchozφho oddφlu a p°elo₧φme ho jako dvojici seskupenφ, Program.exe a PoΦty.dll . To u₧ umφme.
Umφstφme-li oba soubory do tΘho₧ adresß°e, nap°. do C:\Pokus , bude vÜe v po°ßdku, program spustφme p°φkazem
Pokus
a pob∞₧φ bez problΘm∙ (samoz°ejm∞ pokud k n∞mu operaΦnφ systΘm najde cestu).
Stejn∞ dob°e ale m∙₧eme soubor PoΦty . dll umφstit do adresß°e C:\Pokus\PoΦty . Ani tentokrßt nevzniknou problΘmy.
Pokud nßm takovΘto umφst∞nφ nevyhovuje, m∙₧eme pou₧φt konfiguraΦnφ soubor aplikace. To je XML soubor se jmΘnem shodn²m se jmΘnem äspouÜt∞cφhoô seskupenφ (tedy souboru, se t°φdou obsahujφcφ vstupnφ bod aplikace) a s p°φponou .config . V n∞m lze specifikovat mimo jinΘ i jmΘno podadresß°e zßvislΘho seskupenφ, a to v prvku <probing> v parametru privatePath . Prvek <probing> musφ b²t vno°en do prvku <assemblyBinding> a ten je vno°en do prvku <runtime> v prvku <configuration> , kter² je na nejvyÜÜφ ·rovni.
Parametr privatePath m∙₧e obsahovat i n∞kolik adresß°∙ odd∞len²ch st°ednφkem. V₧dy to budou jmΘna podadresß°∙ domovskΘho adresß°e aplikace.
Vezm∞me op∞t seskupenφ Program.exe a PoΦty.dll . Seskupenφ PoΦty.dll chceme umφstit do podadresß°e C:\Pokus\Hokus . Vytvo°φme proto konfiguraΦnφ soubor Program.exe.config s nßsledujφcφm obsahem:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="Hokus" />
</assemblyBinding>
</runtime>
</configuration>
Pozor: Na konci prvku <assemblyBinding> v °et∞zci asm.v1 je Φφslice 1 (jedna), nikoli pφsmeno l (äelô).
Soubor Program.exe.config ulo₧φme do domovskΘho adresß°e aplikace, spolu se souborem Program.exe (v naÜem p°φpad∞ tedy do C:\Pokus ). Soubor PoΦty.dll umφstφme do podadresß°e C:\Pokus\Hokus . Program bude op∞t fungovat.
JmΘno konfiguraΦnφho souboru musφ obsahovat celΘ jmΘno spustitelnΘho souboru, tj. vΦetn∞ p°φpony exe .
Soubor PoΦty.dll m∙₧eme takΘ umφstit do podadresß°e C:\Pokus\Hokus\PoΦty .
Jak se tedy hledß? P°edchozφ informace lze shrnout do nßsledujφcφch pravidel. P°itom je t°eba v∞d∞t, ₧e v metadatech seskupenφ je uvedeno pouze samotnΘ jmΘno seskupenφ, na n∞₧ odkazuje. Toto jmΘno neobsahuje cestu ani p°φponu.
Obsahuje-li tedy spouÜt∞n² program odkaz na jinΘ seskupenφ jmΘnem PoΦty , budou se za b∞hu prohledßvat adresß°e v nßsledujφcφm po°adφ a bude se v nich hledat soubor PoΦty.dll :
• Domovsk² adresß° aplikace, nap°. C:\Pokus .
• Podadresß° se jmΘnem shodn²m se jmΘnem seskupenφ, nap°. C:\Pokus\PoΦty .
• Podadresß° odpovφdajφcφ prvnφ z cest uveden²ch v privatePath , tedy nap°. C:\Pokus\Hokus .
• Jeho podadresß° se jmΘnem shodn²m se jmΘnem seskupenφ, nap°. C:\Pokus\Hokus\PoΦty .
• Podadresß° odpovφdajφcφ druhΘ z cest uveden²ch v privatePath , pokud je zadßna,
• atd.
Pokud se ani v jednom z t∞chto adresß°∙ nenajde soubor PoΦty.dll , prohledß je .NET jeÜt∞ jednou ve stejnΘm po°adφ, bude ovÜem hledat soubor PoΦty.exe .
Je jasnΘ, ₧e pokud nenφ k dispozici konfiguraΦnφ soubor, p°ipadajφ v ·vahu pouze prvnφ dv∞ mo₧nosti; op∞t se bude nejprve hledat dynamickß knihovna a pak soubor .exe .
Poznamenejme, ₧e p°i p°ekladu se odkazovanΘ seskupenφ hledß
• v pracovnφm adresß°i,
• v adresß°i, kter² obsahuje CLR a kter² pou₧φvß p°ekladaΦ. V tomto adresß°i je ulo₧ena knihovna MSCorLib.dll . Jde nap°. o C:\WinNT\Microsoft.NET\Framework\v1.1.4322 ,
• v jakΘmkoli adresß°i urΦenΘm volbou /lib p°ekladaΦe,
• v jakΘmkoli adresß°i urΦenΘm prom∞nnou LIB prost°edφ.
Pravidla se aplikujφ v uvedenΘm po°adφ. (Knihovnφ seskupenφ dodßvanΘ Microsoftem jsou instalovßna dvakrßt, a to v adresß°i uvedenΘm v bod∞ (2), kde je vyu₧φvß p°ekladaΦ, a v tzv. GAC, o nφ₧ budeme hovo°it dßle.)
SdφlenΘ seskupenφ vyu₧φvß n∞kolik aplikacφ. Instaluje se typicky do globßlnφ mezipam∞ti seskupeni (Global Assembly Cache, GAC).
SdφlenΘ seskupenφ musφ mφt tzv. silnΘ (sdφlenΘ) jmΘno. Jeho zßkladem je dvojice klφΦ∙, ve°ejn² a soukrom². Ty vytvo°φme pomocn²m programem sn.exe , kter² je souΦßstφ instalace SDK pro .NET.
Dßle musφme specifikovat Φφslo verze a p°φpad∞ äkulturuô (jazykovou mutaci). Soubor s klφΦi a dalÜφ ·daje zadßvßme pomocφ atribut∙ pro seskupenφ. PodstatnΘ pro nßs budou p°edevÜφm atributy System.Reflection.AssemblyVersion a System.Reflection.AssemblyKeyFile .
Vytvo°φme sdφlenΘ seskupenφ ze souboru PoΦty.cs .
Nejprve vytvo°φme nov² pßr klφΦ∙ p°φkazem
sn -k klφΦ.snk
Zde p°epφnaΦ ûk °φkß, ₧e chceme vytvo°it novou dvojici klφΦ∙, a klφΦ.snk je jmΘno souboru, do kterΘho bude tato dvojice ulo₧ena. (Op∞t je nezbytnΘ, aby operaΦnφ systΘm naÜel cestu k souboru sn.exe .)
Dßle upravφme zdrojov² text souboru PoΦty.cs takto:
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("klφΦ.snk")]
[assembly: AssemblyVersion("1.0.O.0")]
public class PoΦty
{
public static int f(int n)
{
if (n<0) throw new ArgumentException("Zßporn² parametr");
int s = 1;
while(n > 1)s *= n--;
return s;
}
}
Pak tento soubor p°elo₧φme obvykl²m zp∙sobem. VzniklΘ seskupenφ lze pou₧φvat i nadßle jako soukromΘ, lze ho ale takΘ instalovat do GAC. NejjednoduÜÜφm zp∙sobem, jak to ud∞lat, je p°etßhnout ho myÜφ pomocφ programu Windows Explorer do podadresß°e assembly v adresß°i s instalacφ Windows (tedy nap°. do C:\Winnt\assembly ). NejjednoduÜÜφ zp∙sob odinstalovßnφ je prost∞ ho (op∞t pomocφ Windows Exploreru) smazat.
Pozor, nejde o prostΘ kopφrovßnφ, tak₧e jin² program û nap°. Windows Commander nebo p°φkaz operaΦnφho systΘmu COPY û zde nem∙₧e Explorer nahradit . Adresß° assembly mß toti₧ pom∞rn∞ slo₧itou vnit°nφ strukturu, kterou Explorer nezobrazuje. Obsahuje podadresß°e pro r∙znΘ verze, r∙znΘ jazykovΘ mutace atd. tΘho₧ seskupenφ. Krom∞ toho, pokud se seskupenφ sklßdß z n∞kolika r∙zn²ch soubor∙ (nap°. ze souboru s manifestem a ze soubor∙ s jednotliv²mi moduly), postarß se explorer o p°ekopφrovßnφ vÜech Φßstφ seskupenφ, i kdy₧ p°etßhneme pouze Φßst obsahujφcφ manifest.
Lze ovÜem vyu₧φt takΘ utilitu gacutil.exe . Ta se hodφ zejmΘna p°i automatickΘ instalaci.
SdφlenΘ seskupenφ je digitßln∞ podepsßno algoritmem podobn²m Üifrovßnφ s ve°ejn²m klφΦem. Ve°ejn² klφΦ je souΦßstφ tohoto seskupenφ a mohl by i slou₧it jako souΦßst jeho identifikace. Proto₧e je ale velice dlouh², pou₧φvß se mφsto n∞j tzv. token ve°ejnΘho klφΦe (public key token). To je 128bitovß hodnota, kterß z ve°ejnΘho klφΦe vznikne pou₧itφm jistΘho heÜovacφho algoritmu a je souΦßstφ identifikace seskupenφ.
Jestli₧e nechceme zadßvat atributy, tj. jestli₧e chceme pou₧φt p∙vodnφ zdrojov² text programu,
using System;
public class PoΦty
{
public static int f(int n)
{
if (n<0) throw new ArgumentException("Zßporn² parametr");
int s = 1;
while(n > 1)s *= n--;
return s;
}
}
postupujeme takto:
Nejprve vytvo°φme modul p°φkazem
csc /t:module PoΦty.cs
Pak sestavφme dynamickou knihovnu p°φkazem
al /out:PoΦty.dll /t:library /v:1.0.0.0 /keyf:klφΦ.snk PoΦty.netmodule
I kdy₧ se v²slednΘ seskupenφ sklßdß ze dvou soubor∙ ( PoΦty.dll a PoΦty.netmodule ), p°i instalaci p°etßhneme myÜφ do adresß°e assembly pouze soubor PoΦty.dll . Explorer se postarß o ostatnφ sßm.
╚φsla verzφ sdφlen²ch seskupenφ majφ v .NET strukturu
Hlavnφ.vedlejÜφ.sestavenφ.revize
Jestli₧e se liÜφ hlavnφ nebo vedlejÜφ Φφslo revize, poklßdß se sestavenφ v₧dy za nekompatibilnφ s po₧adovan²m. To ale lze obejφt pomocφ konfiguraΦnφch soubor∙. (Tak pravφ dokumentace. Podle m²ch zkuÜenostφ poklßdß prost°edφ .NET za nekompatibilnφ verze, kterΘ se liÜφ v kterΘmkoli c Φφsel.)
P°elo₧φme knihovnu PoΦty znovu, ovÜem tentokrßt s Φφslem verze 1.1.0.0, a nahradφme p∙vodnφ soubor nov²m. JinΘ zm∞ny nebudou pro ·Φely tohoto p°φkladu pot°eba. (Pokud mßme soubor v GAC, musφme ho odinstalovat, nebo¥ jinak bychom m∞li dv∞ verze vedle sebe. M∙₧eme ale knihovnu ponechat v adresß°i aplikace, pro naÜe ·Φely to staΦφ. Nesmφme ale zapomenout p∙vodnφ verzi odstranit z GAC.)
Jestli₧e nynφ aplikaci spustφme, dostaneme pom∞rn∞ obsßhlΘ chybovΘ hlßÜenφ, kterΘ bude konΦit sd∞lenφm
Comparing the assembly name resulted in the mismatch: Minor Version
co₧ znamenß, ₧e nalezenΘ seskupenφ se liÜφ od po₧adovanΘho ve vedlejÜφm Φφsle verze. K tomu, aby se program dal spustit, staΦφ vytvo°it konfiguraΦnφ soubor Program.exe.config s nßsledujφcφm obsahem:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="PoΦty" publicKeyToken="bf97be80f07ba3bd"
/>
< oldVersion="1.0.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Poznamenejme, ₧e hodnota v atributu publicKeyToken se bude liÜit. Zjistφme ji nap°. pomocφ programu ildasm.exe z odkazu na sestavenφ PoΦty v sestavenφ Program .
Element bindingRedirect udßvß starou a novou po₧adovanou verzi. Atribut oldVersion smφ udßvat rozmezφ, nap°. oldVersion="1.0.0.0-1.0.99.99" .
KonfiguraΦnφ soubor aplikace lze vytvo°it pomocφ nßstroj∙ platformy .NET. Ve Windows 2000 zvolφme z nabφdky Start polo₧ku Control Panel a v n∞m polo₧ku Administrative Tools . (V jin²ch verzφch Windows se p°φstup k administrativnφm nßstroj∙m m∙₧e liÜit.) Zde zvolφme Microsoft .NET Framework configuration . V nabφdce Tasks vybereme Manage Individual Applications, Add an Application to Configure a v dialogovΘm okn∞ vyhledßme naÜi aplikaci.
V pod°φzen²ch polo₧kßch pak zvolφme Configured Assemblies , Configure an Assembly , Choose an assembly from the list a na kart∞ Binding Policy nastavφme po₧adovanou novou verzi. P°φsluÜn² pr∙vodce automaticky vytvo°φ nebo upravφ konfiguraΦnφ soubor aplikace.
Pod oznaΦenφm reflexe (reflection) se skr²vajφ nßstroje pro pokroΦilejÜφ prßci s datov²mi typy. Jde nap°. o mo₧nost zjistit podrobnΘ informace o datovΘm typu, kter² v dob∞ psanφ programu neznßme, vytvo°it jeho instanci, volat jeho metody atd.
V∞tÜina nßstroj∙ pro reflexi je v prostoru jmen System.Reflection . Nßstroje pro vytvß°enφ nov²ch datov²ch typ∙ za b∞hu programu najdeme v prostoru jmen System.Reflec¡tion.Emit .
Reflexe je v C# (a ve vÜech jazycφch pro platformu .NET, nebo¥ vÜechny se opφrajφ o stejnΘ knihovny) zalo₧ena p°edevÜφm na t°φd∞ System.Type a na n∞kolika dalÜφch pomocn²ch t°φdßch, je₧ obsahujφ informace o slo₧kßch datov²ch typ∙ ( MemberInfo , FieldInfo , MethodInfo , ConstructorInfo atd.).
Mechanizmus reflexe umo₧≥uje um∞t pracovat nejen s typy, ale i se seskupenφmi, moduly a slo₧kami. Hierarchicky nejvyÜÜφ je aplikaΦnφ domΘna, p°edstavovanß t°φdou System.AppDomain . Za nφ nßsleduje seskupenφ, p°edstavovanΘ t°φdou System.Re¡flection.Assembly , a modul, p°edstavovan² t°φdou System.Reflec¡tion.Module . O t°φdßch, reprezentujφcφch datov² typ ( System.Type ) a slo₧ky ( System.Reflec¡tion.Mem¡berInfo , System.Reflection . PropertyInfo a dalÜφch) jsme se ji₧ zmi≥ovali.
Poznamenejme, ₧e v p°edchozφm odstavci slovo ähierarchieô neoznaΦuje hierarchii ve smyslu d∞d∞nφ, ale hierarchii ve smyslu vztahu celek û Φßst.
Vztahy (tentokrßt z hlediska d∞d∞nφ) mezi nejΦast∞ji pou₧φvan²mi t°φdami pro reflexi ukazuje obr. 4.
Obr. 4 N∞kterΘ z t°φd pou₧φvan²ch p°i reflexi. Kde nenφ vyznaΦen prostor jmen,
rozumφ se System.Rexlection
Mßme k dispozici dynamickou knihovnu, je₧ obsahuje pouze nßsledujφcφ t°φdu:
// P°elo₧φme p°φkazem csc /t:library testik.cs
public class Testφk
{
static Testφk() // Statick² konstruktor
{
System.Console.WriteLine("Testφk se hlßsφ");
}
int i;
public Testφk(int y){ i = y;} // Konstruktor
public void VypiÜ() // Volanß metoda
{
System.Console.WriteLine("i = {0}", i);
}
}
Chceme napsat program, kter² jako parametr p°φkazovΘ °ßdky dostane znakov² °et∞zec obsahujφcφ jmΘno tΘto dynamickΘ knihovny. JedinΘ dalÜφ informace, kterΘ bude mφt nßÜ program k dispozici, jsou, ₧e
• seskupenφ obsahuje deklaraci jedinΘho datovΘho typu, a to t°φdy,
• tato t°φda mß konstruktor s jednφm parametrem typu int a
• obsahuje ve°ejn∞ p°φstupnou metodu bez parametr∙ void VypiÜ() .
V programu vypφ?eme informace o slo?kßch tΘto neznßmΘ toφdy, vytvooφme instanci tΘto toφdy a zavolßme jejφ metodu VypiÜ() .
Postup bude nßsledujφcφ: Nejprve musφme v programu vytvooit instanci toφdy Assembly , je₧ bude reprezentovat seskupenφ obsahujφcφ neznßmou t°φdu. K tomu pou₧ijeme statickou metodu Assembly.LoadFrom() , jejφm₧ parametrem je znakov² °et∞zec p°edstavujφcφ jmΘno souboru s tφmto seskupenφm.
Program bude pochopiteln∞ zaΦφnat direktivami
using System;
using System.Reflection;
Je-li nßzev souboru obsa₧en v °et∞zci s , zφskßme odkaz na odpovφdajφcφ seskupenφ p°φkazem
Assembly a = Assembly.LoadFrom(s);
Pokud se tato operace nepoda°φ, m∙₧e vzniknout v²jimka typu ArgumentNullException , FileNotFoundException , SecurityException a jeÜt∞ n∞kterΘ dalÜφ, proto bude t°eba tuto operaci û spolu s nßsledujφcφmi û uzav°φt do bloku try .
Seznam typ∙, definovan²ch v tomto seskupenφ, zφskßme pomocφ metody GetTypes() t°φdy Assembly , je₧ vracφ odkaz na pole typu Type :
Type[] t = a.GetTypes();
Proto₧e vφme, ₧e toto seskupenφ obsahuje jedin² typ, nemusφme se zab²vat anal²zou vrßcenΘho pole a m∙₧e dßle pou₧φt p°φmo jeho nult² prvek.
Dßle vypφÜeme informace o slo₧kßch tΘto t°φdy. Tyto informace zφskßme pomocφ metody GetMembers() , je₧ vrßtφ odkaz na pole s informacemi o slo₧kßch:
MemberInfo[] mip = t[0].GetMembers();
foreach(MemberInfo m in mip) Console.WriteLine(m);
NaÜφm dalÜφm ·kolem je vytvo°it instanci tohoto typu. K tomu pou₧ijeme statickou metodu System.Reflection.Activat¡or.CreateInstance() . Jejφm prvnφm parametrem je instance t°φdy Type , reprezentujφcφ datov² typ, jeho₧ instanci chceme vytvo°it, a druh²m je pole typu object[] , obsahujφcφ parametry konstruktoru. Tato metoda vrßtφ odkaz na object :
object obj = Activator.CreateInstance(t[0], new object[]{1});
Nakonec chceme zavolat metodu VypiÜ() . Instanci obj nelze p°etypovat, proto₧e v dob∞ p°ekladu neznßme jmΘno typu, o kter² jde. Proto musφme pomocφ t°φdy Type zφskat instanci t°φdy MethodInfo popisujφcφ tuto metodu,
MethodInfo mti = t[0].GetMethod("VypiÜ");
a zavolat ji prost°ednictvφm metody Invoke() :
mti.Invoke(obj, null);
Druh² parametr p°edstavuje odkaz na pole typu object obsahujφcφ parametry metody. Proto₧e naÜe metoda nemß ₧ßdnΘ parametry, pou₧ijeme hodnotu null , je₧ p°edstavuje äukazatel nikamô. Program p °elo₧φme ho p°φkazem
csc Program.cs
VÜimn∞te si, ₧e zde neuvßdφme odkaz na dynamickou knihovnu, s nφ₧ pracujeme. Nenφ to nutnΘ, nebo¥ nßÜ program neobsahuje ₧ßdn² odkaz na t°φdu Testφk .
Tento ·vod do prßce se seskupenφmi samoz°ejm∞ nenφ vyΦerpßvajφcφ, alespo≥ pokud jde o obsah. Nabφzφ ale alespo≥ zßkladnφ informace o tom, jak seskupenφ vytvo°it a jak je pou₧φvat. Nehovo°ili jsme nap°. o problematice jazykov²ch mutacφ (äkulturyô), o mo₧nosti odlo₧it podpis seskupenφ (kdy certifikovanß autorita potvrdφ platnost seskupenφ po dokonΦenφ v²voje) atd. DalÜφ informace m∙₧ete najφt nap°φklad v knihßch z nßsledujφcφho seznamu.
• Jeffrey Richter: Applied Microsoft .NET Framework Programmig . Microsoft Press 2002.
ISBN 0-7356-1422-9. (╚esky: .NET Framework û programovßnφ aplikacφ, Grada Publishing 2002, ISBN 80-247-0450-1.)
Andrew Troelsen: C# and the .NET Framework Platform. Apress, 2002. ISBN 1-893115-59-3.
• International standard ISO/IEC 23270:2003 . Programming languages û C#.
Microsoft C# Language Specifications . Microsoft Press, Redmond 2001. ISBN 0-7356-1448-2.
J. Gough: Compiling for the . NET Common Language Runtime . Prentice Hall, 2002,
ISBN 0-13-062296-6.
• Simon Robinson, K. Scott Allen, Ollie Cornes, Jay Glynn, Zach Greenvoss, Burton Harvey, Christian Nagel, Morgan Skinner, Karli Watson: C# Programujeme profesionßln∞. Computer Press, Praha 2003. ISBN: 80-251-0085-5
D. KaΦmß°: Programujeme .NET aplikace. Computer Press, Praha 2001. ISBN 80-7226-569-5
Miroslav Virius