Prost°edφ .NET: Seskupenφ a prßce s nφm

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Üφ.

Jak vytvo°it seskupenφ

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∙.

P°φklad

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.)

Disasembler

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

DalÜφ zp∙soby, jak vytvo°it seskupenφ

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.

Adresß° soukromΘho seskupenφ

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φ.

P°φklad

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.

KonfiguraΦnφ soubor

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.

P°φklad

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.

Poznßmky

Jak se hledß soukromΘ seskupenφ

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φ

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 .

P°φklad

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.

Poznßmka

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φ.

Jinß mo₧nost vytvo°enφ sdφlenΘho 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.

Verze

╚φ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°φklad

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" .

Vytvo°enφ konfiguraΦnφho souboru

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.

Prßce s neznßm²m seskupenφm: reflexe

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.).

Hierarchie

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

P°φklad

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 .

Co dodat

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.

Literatura o prost°edφ .NET Framework

•  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.)

  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#.

  1. Microsoft C# Language Specifications . Microsoft Press, Redmond 2001. ISBN 0-7356-1448-2.

  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

  1. D. KaΦmß°: Programujeme .NET aplikace. Computer Press, Praha 2001. ISBN 80-7226-569-5

Miroslav Virius