+ All Categories
Home > Documents > curs .NET 7.pdf

curs .NET 7.pdf

Date post: 14-Apr-2018
Category:
Upload: andera4u
View: 313 times
Download: 0 times
Share this document with a friend

of 27

Transcript
  • 7/27/2019 curs .NET 7.pdf

    1/27

    Curs 7 / Pagina 1 din 27

    1

    Creare CLR, AppDomain, si Reflection

    Metadata: una din cele mai importante trasaturi ale .NET-ului

    Metadata descrie tipul unui camp precum si metodele asociate acestuia.

    Metadata:

    contine informatia de care un tip de data are nevoie pentru a se defini; este folosita de GC pentru a determina daca un obiect mai este valid in heap; este folosita de utilitarele de dezvoltare pentru a construi help senzitiv utilizat in

    momentul scrierii codului (vezi Intellisense);

    este folosita in procesul de serializare si deserializare al obiectelor.Actiunea de examinare a metadatei se numeste reflection.

    Reflection permite dezvoltatorilor de a construi in mod dinamic aplicatii extensibile.

    De exemplu, oricine poate scrie un tip de data si sa-l impacheteze intr-un assembly.

    Cand altcineva foloseste acest tip, datorita informatiilor din metadata, un mediu de

    dezvoltare (Visual Studio .NET, etc.) poate integra acest tip in cadrul proiectului si sa

    afiseze proprietatile expuse de acest tip.

    CLR modalitati de instantiere

    Cadrul de lucru .NET ruleaza deasupra sistemului de operare. Acest lucru inseamna ca.NET trebuie sa foloseasca tehnologii pe care Windows sa le inteleaga.

    CLR a fost implementat ca un server COM continut intr-un DLL ; deci acesta are o

    interfata COM standard, are atribuit un GUID. Toate aceste informatii sunt scrise in

    registri in momentul instalarii serverului COM.

    Definitiile pentru acest server se gasesc in MSCorEE.h (definitia interfetei

    ICorRuntimeHostsi definitiile GUID-urilor).

    Pentru a crea o instanta a acestui server va trebui sa utilizam functia CorBindToRuntimeEx

    in loc de functia CoCreateInstance.

    Functia CorBindToRuntimeEx este implementata in MSCorEE.dll ce se gaseste in

    subdirectorul System32 al sistemului de operare, dar serverul nu este in acest DLL.

    Aceasta biblioteca este folosita pentru a determina versiunea corecta a CLR-ului ce se va

    crea. Biblioteca MScorWks.dll contine versiunea pentru statii de lucru, iar MSCorSvr.dll

    contine versiunea pentru server.

    O aplicatie poate suprascrie valorile implicite necesare pentru crearea serverului plasand

    informatii intr-un fisier de configurare XML, ca in exemplul urmator :

    Daca safemode = false, atunci se incarca versiunea de CLR cea mai recenta ce este

    compatibila cu versiunea aplicatiei noastre.

  • 7/27/2019 curs .NET 7.pdf

    2/27

    Curs 7 / Pagina 2 din 27

    2

    MS determina ce versiune de CLR este compatibila cu alte versiuni prin crearea de

    informatii in registri. Aceste se gasesc sub cheia

    HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\Policy

    Functia CorBindToRuntimeEx returneaza un pointer la interfata unmanaged

    ICorRuntimeHost (definita in MSCorEE.h). Aplicatia poate apela metodele definte deaceasta interfata pentru a initializa CLR.

    Un singur proces poate crea numai o instanta a unui server COM CLR.

    Dintre multele actiuni efectuate in timpul initializarii CLR, enumeram:

    Se creaza zona heap managed in care vor fi alocate obiectele referinta si pe care ova gestiona GC.

    Se creaza un thread pool folosit de orice tip managed ale carui assembly suntincarcati in proces.

    Se creaza un AppDomain. Un AppDomain poate fi asimilat ca un container logicpentru o multime de assemblies. Primul AppDomain creat se numeste AppDomain

    implicit. Acest AppDomain implicit este distrus cand procesul Windows se

    termina. CLR poate crea mai multe AppDomain, in afara de cel implicit.

    AppDomain

    Sunt reprezentate de obiecteAppDomain.

    Un proces poate contine mai multeAppDomain, iar unAppDomain poate contine unul sau

    mai multe fire.

    AppDomain sunt create cu metoda CreateDomain.

    Instantele AppDomain sunt folosite pentru a incarca si executa assemblies.

    Clasa AppDomain implementeaza o multime de evenimente ce permite aplicatiilor sa

    raspunda cand un assembly este incarcat, cand un AppDomain este descarcat sau cand este

    lansata o exceptie necunoscuta.

    Aceasta clasa implementeaza MarshalByRefObject, si interfetele _AppDomain si

    IEvidenceFactory.

    Interfata _AppDomain implementeaza o multime de evenimente ce permit aplicatiilor sa

    raspunda cand un assembly este incarcat, unAppDomain va fi descarcatsau sa trateze

    exceptii.

    MarshalByRefObject este clasa de baza pentru obiectele ce comunica in afara frontierelor

    aplicatiei prin schimbul de mesage folosind un proxy.Obiectele ce nu sunt mostenite din MarshalByRefObjectsunt implicit transferate prin

    valoare.

    Obiectele MarshalByRefObjectsunt accesate direct in interiorul domeniului. Pentru a

    realiza acest lucru se foloseste un proxy, ce este pasat aplicatiei remote.

    Toate apelurile se realizeaza prin cadrul acestui proxy (tehnica asemanatoare si la

    COM/DCOM).

    Public Properties

  • 7/27/2019 curs .NET 7.pdf

    3/27

    Curs 7 / Pagina 3 din 27

    3

    !

    "#

    $ %

    # &

    ## "%'(()

    # "%%'(()

    $ *

    !

    *

    $ *

    $&+ *

    $ *

    $&+*

    *,"'

    )

    ,

    -%.,

    & *

    ! .%

    -'

    )

    **,-

  • 7/27/2019 curs .NET 7.pdf

    4/27

    Curs 7 / Pagina 4 din 27

    4

    !

    .&

    !

    *.

    &

    $

    /')

    !

    0%%!

    1'

    )

    ",

    ')

    !

    $21 *

    %%$2%+ $

    %0,%2%%

    1 *1&

    #

    &%

    %

    ## ,.%

    %

    #

  • 7/27/2019 curs .NET 7.pdf

    5/27

    Curs 7 / Pagina 5 din 27

    5

    # ,

    .%

    %

    !

    **%

    + +

    &1 *

    &" *

    + *

    #. *3.

    "" *

    " *

    +. *.%

    2')

    !

    *&*,%%

    $45502.%

    .

    6'

    )

    !

    *,

    Exemplu pentru tratarea unui eveniment.

    [C#]

    public virtual event AssemblyLoadEventHandler AssemblyLoad;

    2%&1&%#22

    1& &

  • 7/27/2019 curs .NET 7.pdf

    6/27

    Curs 7 / Pagina 6 din 27

    6

    !

    &1/%%0#$0

    .

    %0%"

    78040559.0-[C#]

    using System;

    using System.Reflection;

    class Test {

    public static void Main()

    {

    AppDomain currentDomain = AppDomain.CurrentDomain;currentDomain.AssemblyLoad += newAssemblyLoadEventHandler(MyAssemblyLoadEventHandler);

    PrintLoadedAssemblies(currentDomain);

    // Lists mscorlib and this assembly

    // You must supply a valid fully qualified assembly name here.

    currentDomain.CreateInstance("System.Windows.Forms, Version,

    Culture, PublicKeyToken", "System.Windows.Forms.TextBox");

    // Loads System, System.Drawing, System.Windows.Forms

    PrintLoadedAssemblies(currentDomain);// Lists all five assemblies

    }

    static void PrintLoadedAssemblies(AppDomain domain)

    {

    Console.WriteLine("LOADED ASSEMBLIES:");

    foreach (Assembly a in domain.GetAssemblies())

    {

    Console.WriteLine(a.FullName);

    }

    Console.WriteLine();

    }

    static void MyAssemblyLoadEventHandler(object sender,AssemblyLoadEventArgs args)

    {Console.WriteLine("ASSEMBLY LOADED: " +

    args.LoadedAssembly.FullName);Console.WriteLine();

    }

    }

  • 7/27/2019 curs .NET 7.pdf

    7/27

    Curs 7 / Pagina 7 din 27

    7

    #$%&

    #

    0789*#$&+'%0%)&*,749,$&+'%0%):

    7559;*,:.

    >%2>?%@0%0%6$

    0%>%0%

    >>

  • 7/27/2019 curs .NET 7.pdf

    8/27

    Curs 7 / Pagina 8 din 27

    8

    >

    82"

    "' #

    &%. '(8)

    6%6. %

    1.

    .

    6&.

    . ,6"*,

    . -

    &+. *

    &2

    "

    [C#]

    using System;

    using System.Reflection;

    class Test {

    static void Main() {

    InstantiateINT32(false); // Failed!

    InstantiateINT32(true); // OK!

    }

    static void InstantiateINT32(bool ignoreCase) {

    try {

    AppDomain currentDomain = AppDomain.CurrentDomain;

    object instance = currentDomain.CreateInstanceAndUnwrap(

    "mscorlib",

    "SYSTEM.INT32",

    ignoreCase,BindingFlags.Default,

    null,

    null,

    null,

    null,

    null

    );

    Console.WriteLine(instance.GetType());

    } catch (TypeLoadException e) {

    Console.WriteLine(e.Message);

  • 7/27/2019 curs .NET 7.pdf

    9/27

    Curs 7 / Pagina 9 din 27

    9

    }

    }

    }

    Exemplu pentru CreateDomain (vezi MS). Importante sunt etapele de creare, care

    urmaresc prototipul metodei CreateDomain ce va fi folosita.

    // Set up the AppDomainSetup

    AppDomainSetup setup = new AppDomainSetup();

    setup.ApplicationBase = "(some directory)";

    setup.ConfigurationFile = "(some file)";

    // Set up the Evidence

    Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;

    Evidence evidence = new Evidence(baseEvidence);

    evidence.AddAssembly("(some assembly)");

    evidence.AddHost("(some host)");

    // Create the AppDomain

    AppDomain newDomain = AppDomain.CreateDomain("newDomain", evidence,

    setup);

    Clasa AppDomainSetup = Contine informatii pentru legare assembly ce pot fiadaugate la o instanta a unui AppDomain.

    62&&&2

    )

    &$2)

    & %

    &

    #

    % %

    %" %%

    %/#

    ## %

    %

    %

    1

  • 7/27/2019 curs .NET 7.pdf

    10/27

    Curs 7 / Pagina 10 din 27

    10

    1*2 2.

    ## &

    ###

    %

    %%

    #

    2

    *2?@#%:'2)%%AB%'2$)2

    2?@&AB;

    2

    !""

    #$#""%&'()*+,-".

    /"!"

    ""01""""!""

    .1

    #

    !

    *$2

  • 7/27/2019 curs .NET 7.pdf

    11/27

    Curs 7 / Pagina 11 din 27

    11

    ,

    $"* %

    $2 %

    1! %

    !

    " 2

    && &

    &/ &

    ,&

    -')

    !

    **,-

    &

    0

    /'

    )

    !

    0%%!

    /

    ')

    !

    6% 6%

    %')

    !

    "%*,

    2')

    !

    *&*,

    %%$45502.

  • 7/27/2019 curs .NET 7.pdf

    12/27

    Curs 7 / Pagina 12 din 27

    12

    %.

    6'

    )!

    *,

    AppDomain se caracterizeaza prin: Sunt izolate unele de altele un AppDomainnu poate vedea obiectele create de alt

    AppDomain darpoate comunica cu tipuri si obiecte din alte AppDomain. Aceasta

    caracteristica face ca AppDomain sa poata fi descarcate din proces. CLR nu are

    posibilitatea de a descarca un singur assembly. Assemblies vor fi descrcati odata cu

    AppDomain care le-a incarcat.

    Pot fi configurate si securizate individual. Astfel se determina drepturile maximeatribuite unui assembly ce ruleaza intr-un AppDomain. Putem gestiona securitatea

    unui AppDomain folosind metoda SetAppDomainPolicy.

    Clasa System.AppDomainSetup ne permite sa definim si sa interogam setarile unui

    AppDomain. Aceste setari includ urmatoarele :

    ApplicationName un string folosit pentru a identifica un AppDomain.ApplicationBase un director unde CLR va cauta assemblies.

    PrivateBinPath o multime de directoare unde CLR va cauta sa localizeze assmblies cu

    nume slabe .

    ConfigurationFile numele caii unui fisier de configurare ce contine regului pe care CLR

    le va utiliza pentru a localiza assemblies. Fisierul contine de asemenea setari pentru

    remoting, aplicatii Web, etc.

    LoaderOptimization un flag ce indica modul cum CLR trateaza assemblies incarcati :

    ca domain neutral sau single-domain .

    Observatie: S-ar putea sa fie periculos sa se ruleze mai multe aplicatii unmanaged intr-

    un singur proces, pentru ca acestea pot avea acces la datele si codul din cadrul celeilalte

    aplicatii.

    Accesarea obiectelor in afara unui AppDomain

    Codul dintr-un domeniu poate comunica cu tipuri si obiecte continute in alte domenii.

    Majoritatea tipurilor sunt transferate prin valoare in cadrul altor domenii. Obiectul este

    serializat in cadrul unui bloc de memorie si apoi transmis altui domeniu. Domeniul ce

    primeste acest obiect il va deserializa. Domeniul destinatie nu are acces la obiectul

    original.

    Obiectele transmise prin valoare trebuie sa aiba atributul System.Serializable.

    Deserializarea obiectului are ca efect incarcarea de catre CLR a tipului de assembly

    necesar. Daca CLR nu poate incarca acel assembly, atunci deserializarea nu are loc si va fiemisa o exceptie.

    Tipurile ce sunt derivate din System.MarshalByRefObject pot fi de asemenea transmise

    altor domenii. In acest caz se transmite o referinta la obiect. Obiectul original ramine in

    domeniul sursa (acolo unde a fost creat obiectul).

    Nu exista o corespondenta de 1-1 intre fire si AppDomain. Cand se executa un fir dintr-un

    doemniu in alt domeniu, firul tranziteaza intre cele doua AppDomain, deci acesta este

    executat in mod sincron. La un moment dat, un fir este considerat sa fie exact intr-un

    domeniu.

  • 7/27/2019 curs .NET 7.pdf

    13/27

    Curs 7 / Pagina 13 din 27

    13

    Putem apela metoda statica GetDomain din System.Threading.Threadpentru a obtine o

    referinta la un obiect System.AppDomain si a identifica domeniul unde se executa firul.

    Cand un AppDomain este descarcat, toate firele din acest domeniu vor fi terminate, CLR-

    ul fortand o exceptie de tipul ThreadAbortException, de asemenea vor fi descarcate si

    assemblies continuti in AppDomain.

    Evenimente AppDomain

    Evenimentele pe care le putem trata sunt:

    AssemblyLoad apare cand CLR incarca un assembly intr-un domeniu. Functia ce trateaza

    evenimentul primeste un obiect System.Reflection.Assembly ce identifica assembly

    incarcat.

    DomainUnload - apare inainte ca AppDomain sa fie descarcat. Evenimentul nu apare

    cand procesul ce contine AppDomain este terminat.

    ProcessExit - apare inainte ca procesul sa se termine. Evenimentul este lansat numai

    pentru AppDomain implicit.

    UnhandledException - emis cand apare o exceptie intr-un AppDomain.

    AssemblyResolve apare cand CLR nu poate localiza un assembly cerut de un domeniu.Functia ce trateaza evenimentul primeste un string ce identifica numele assembly lipsa.

    ResourceResolve acelasi lucru ca la AssemblyResolve, numai ca este vorba de o resursa.

    TypeResolve Acelasi lucru ca mai sus, numai ca este vorba de un tip de data.

    Din nou despre Reflection

    Metadata este constituita dintr-o multime de tabele. Cand construim un assembly sau un

    modul, compilatorul creaza o serie de tabele: tabela de definitie a tipurilor, tabela de

    definitie a campurilor, tabela de definitie a metodelor, etc.

    Spatiul de nume System.Reflection din FCL contine mai multe tipuri ce permit sa scriem

    cod ce obtine informatii din aceste tabele. Tipurile din acest spatiu de nume ofera un

    model obiect peste metadata continuta in assembly sau modul.

    Cu ajutorul acestor tipuri putem enumera toate tipurile dintr-o tabela de definitie a

    tipurilor. Pentru fiiecare tip putem obtine tipul de baza, ce interfete implementeaza.

    De asemenea putem obtine campurile, metodele, proprietatile, atributele si evenimentele

    unui tip.

    Metoda reflection este cel mai des folosita cu clasele de biblioteci pentru a construi

    ierarhia corecta a definitiei tipurilor.

    Aceasta metoda poate fi folosita pentru a incarca un assembly in mod explict, apoi sa

    construiasca un obiect de un anumit tip (tip gazduit de acest assembly) si apoi sa apeleze

    metodele pe acest obiect (ceva asemanator cu LoadLibrary si GetProcAddress din Win32

    API) se realizeaza legarea intarziata .

    Obtinerea tipurilor unui assembly (reflection method)

    Exemplu

    using System;

    using System.Reflection;

    class App

    {

    static void Main()

  • 7/27/2019 curs .NET 7.pdf

    14/27

    Curs 7 / Pagina 14 din 27

    14

    {

    Assembly assem = Assembly.GetExecutingAssembly();

    Reflector.ReflectOnAssembly(assem);

    }

    }

    public class Reflector

    {

    public static void ReflectOnAssembly(Assembly assem)

    {

    WriteLine(0, "Assembly: {0}", assem);

    // Find Modules

    foreach (Module m in assem.GetModules())

    {

    WriteLine(1, "Module: {0}", m);

    // Find Types

    foreach (Type t in m.GetTypes())

    {

    WriteLine(2, "Type: {0}", t);

    // Find Members

    foreach (MemberInfo mi in t.GetMembers())

    WriteLine(3, "{0}: {1}", mi.MemberType, mi);

    }

    }}

    private static void WriteLine(Int32 indent, String format,

    params Object[] args)

    {

    Console.WriteLine(new String( , 3 * indent) + format, args);

    }

    }

    class SomeType

    {

    public class InnerType {}

    public Int32 SomeField = 0;

    private static String goo = null;

    private void SomeMethod() { }private TimeSpan SomeProperty

    {

    get { return new TimeSpan(); }

    set { }

    }

    public static event System.Threading.ThreadStart SomeEvent;

    private void NoCompilerWarnings()

    {

    // This code is here just to make the compiler warnings go

    away.

    SomeEvent.ToString();

    goo.ToString();

    }

    }

    Rezultatul este:

    Assembly: p7_reflection, Version=1.0.1783.28359, Culture=neutral, PublicKeyToken

    =null

    Module: p7_reflection.exe

    Type: App

    Method: Int32 GetHashCode()

    Method: Boolean Equals(System.Object)

  • 7/27/2019 curs .NET 7.pdf

    15/27

    Curs 7 / Pagina 15 din 27

    15

    Method: System.String ToString()

    Method: System.Type GetType()

    Constructor: Void .ctor()

    Type: Reflector

    Method: Int32 GetHashCode()

    Method: Boolean Equals(System.Object)

    Method: System.String ToString()Method: Void ReflectOnAssembly(System.Reflection.Assembly)

    Method: System.Type GetType()

    Constructor: Void .ctor()

    Type: SomeType

    Field: Int32 SomeField

    Method: Int32 GetHashCode()

    Method: Boolean Equals(System.Object)

    Method: System.String ToString()

    Method: Void add_SomeEvent(System.Threading.ThreadStart)

    Method: Void remove_SomeEvent(System.Threading.ThreadStart)

    Method: System.Type GetType()

    Constructor: Void .ctor()Event: System.Threading.ThreadStart SomeEvent

    NestedType: SomeType+InnerType

    Type: SomeType+InnerType

    Method: Int32 GetHashCode()

    Method: Boolean Equals(System.Object)

    Method: System.String ToString()

    Method: System.Type GetType()

    Constructor: Void .ctor()

    Press any key to continue . . .

    GetExecutingAssembly = determina ce assembly contine metoda ce face apel si returneaza

    o refrinta la acest obiect Assembly.

    ReflectOnAssembly = afiseaza numele complet al unui assembly si apoi apeleaza

    GetModules ce returneaza un vector cu elemente de tip System.Reflection.Module.

    Vezi si GetTypes si GetMembers.

    Iesirea este

    Assembly: Reflector, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

    Module: Reflector.exe

    Type: App

    Method: Int32 GetHashCode()

    Method: Boolean Equals(System.Object)Method: System.String ToString()

    Method: System.Type GetType()

    Constructor: Void .ctor()

    Type: Reflector

    Method: Int32 GetHashCode()

    Method: Boolean Equals(System.Object)

    Method: System.String ToString()

    Method: Void ReflectOnAssembly(System.Reflection.Assembly)

  • 7/27/2019 curs .NET 7.pdf

    16/27

    Curs 7 / Pagina 16 din 27

    16

    Method: System.Type GetType()

    Constructor: Void .ctor()

    Type: SomeType

    Field: Int32 SomeField

    Method: Int32 GetHashCode()

    Method: Boolean Equals(System.Object)

    Method: System.String ToString()Method: Void add_SomeEvent(System.Threading.ThreadStart)

    Method: Void remove_SomeEvent(System.Threading.ThreadStart)

    Method: System.Type GetType()

    Constructor: Void .ctor()

    Event: System.Threading.ThreadStart SomeEvent

    NestedType: SomeType+InnerType

    Type: SomeType+InnerType

    Method: Int32 GetHashCode()

    Method: Boolean Equals(System.Object)

    Method: System.String ToString()

    Method: System.Type GetType()

    Constructor: Void .ctor()

    Obtinere assembly dintr-un AppDomain

    Acelasi exemplu ca mai sus in care modificam Main dupa cum urmeaza:

    static void Main()

    {

    foreach (Assembly assem in

    AppDomain.CurrentDomain.GetAssemblies())

    {

    Reflector.ReflectOnAssembly(assem);

    }

    }

    Incarcarea explicita a unui assembly

    Tehnica este asemanatoare cu cea a utilizarii functiei LoadLibrary din Win32 API.

    Tipul System.Reflection.Assembly ofera urmatoarele metode statice pentru a incarca un

    assembly: Load, LoadFrom, si LoadWithPartialName.

    *)+1%&749&1'&):

    1 *, '*) %%749&1'79):1%%749&1'%):

  • 7/27/2019 curs .NET 7.pdf

    17/27

    Curs 7 / Pagina 17 din 27

    17

    1% &%

    749&1'&0):1 *, '*) %%

    749&1'79079):

    1%0%%

    749&1'%0):1 *, '*) %

    %749&1'790790):

    "*)(+

    [C#]

    using System;

    using System.Reflection;

    class Class1

    {

    public static void Main()

    {

    Assembly SampleAssembly;

    // You must supply a valid fully qualified assembly name here.

    SampleAssembly = Assembly.Load("Assembly text name, Version,

    Culture, PublicKeyToken");

    Type[] Types = SampleAssembly.GetTypes();

    // Display all the types contained in the specified assembly.

    foreach (Type oType in Types)

    {

    Console.WriteLine(oType.Name.ToString());

    }}

    }

    Incarcare assembly ca fisiere de date

    Metoda LoadFrom folosita in acest caz pentru a incarca un assembly furnizat ca parametru

    in linia de comanda.

    Presupunem ca avem doua assemblies: SomeTool.exe si Component.dll (un assembly ce

    contine anumite componente pe care le foloseste SomeTool.exe si acestea sunt instalate in:

    C:\SomeTool\SomeTool.exeC:\SomeTool\Component.dll

    Presupunem ca un mai exista un assembly cu acelasi nume, Component.dll dar situat in

    radacina discului C:.

    Utilizatorul va folosi SomeTools.exe pentru a incarca assembly C:\Component.dll si nu cel

    din directorul curent.

  • 7/27/2019 curs .NET 7.pdf

    18/27

    Curs 7 / Pagina 18 din 27

    18

    C:\>C:\SomeTool\SomeTool.exe C:\Component.dll

    SomeTool.exe va incarca assembly C:\Component.dll folosind metoda LoadFrom,

    pasindu-i ca parametru argumentul din linia de comanda.

    CLR va incarca acest assembly. Presupunem ca in metoda Main se face apel la o alta

    metoda ce face referinta la un obiect din Component.dll.

    Ce se va intimpla?

    Va folosi CLR assembly incarcat sau va incarca assembly din directorul curent?

    Deoarece assembly C:\Component.dll a fost incarcat ca un fisier , CLR nu poate sti ca

    Component.dll a fost incarcat, si ca atare va incarca assembly

    C:\SomeTool\Component.dll.

    Algoritmul pentru LoadFrom

    La executia metodei LoadFrom, CLR deschide fisierul specificat si extrage informatii

    referitaore la versiune, cultura si cheia publica din metadata fisierului, apoi intern CLR

    apeleaza metoda Load, pasindu-i informatia de mai sus. Daca un asemenea assembly este

    gasit, CLR compara calea completa a assembly-ului cu cea furnizata in LoadFrom si in cazca sunt identice, va incarca acel assembly.

    Daca parametrii sunt diferiti sau daca Load nu gaseste un asemenea fisier, assembly este

    considerat ca fiind fisier de date si ca atare nu constituie o parte normala a aplicatiei.

    Utilizarea metodei LoadFrom este descurajata de catre documentatia MS, in principal pe

    considerente de viteza de executie si pe faptul ca un assembly incarcat cu aceasta metoda

    este considerat fisier de date , si deci nu face parte din AppDomain.

    Construirea unei ierarhii a tipurilor derivate din Exception

    Exemplul de mai jos afiseaza toate clasele ce sunt derivate in ultima instanta din

    System.Exception.

    Pentru a face acest lucru este necesar sa examinam tipurile din mai multe assemblies.

    Aplicatia va trebui sa incarce in mod explicit toate assemblies pe care vrem sa le

    scanam .

    using System;

    using System.Text;

    using System.Reflection;

    using System.Collections;

    class App

    {

    static void Main()

    {

    // Incarcam in mod explicit assembly pe care// vrem sa aplicam reflection

    LoadAssemblies(); // metoda proprie

    // Initializare contoare

    // totalTypes = numar total tipuri

    // totalExceptionType = numar total tipuri exceptii

    // exceptionTree = list cu tipuri de exceptii

    Int32 totalTypes = 0, totalExceptionTypes = 0;

  • 7/27/2019 curs .NET 7.pdf

    19/27

    Curs 7 / Pagina 19 din 27

    19

    ArrayList exceptionTree = new ArrayList();

    // Iteram prin toate assemblies

    // incarcate in acest AppDomain

    foreach (Assembly a in

    AppDomain.CurrentDomain.GetAssemblies())

    {

    // Iteram prin toate tipurile definite in acest assembly

    foreach (Type t in a.GetTypes())

    {

    totalTypes++;

    // Ignoram tipul daca nu este o clasa publica

    if (!t.IsClass || !t.IsPublic) continue;

    // Construim un string a ierarhiei

    // de derivare a tipului.

    StringBuilder typeHierarchy =

    new StringBuilder(t.FullName, 5000);

    // Presupunem ca tipul nu este derivat din ExceptionBoolean derivedFromException = false;

    // Cercetam sa vedem daca System.Exception

    // este tipul de baza pentru acest tip

    Type baseType = t.BaseType;

    while ((baseType != null) && !derivedFromException)

    {

    // Adaugam tipul de baza la sfarsitul listei

    typeHierarchy.Append("-" + baseType);

    derivedFromException =

    (baseType == typeof(System.Exception));

    baseType = baseType.BaseType;

    }

    // Controlam urmatorul tip

    if (!derivedFromException) continue;

    // Am gasit un tip derivat din Exception

    totalExceptionTypes++;

    // Pentru acest tip derivat din Exception,

    // inversam ordinea tipurilor in ierarhie

    String[] h = typeHierarchy.ToString().Split(-);

    Array.Reverse(h);

    // Construim un nou string cu ierarhia in ordinea

    // Exception -> tip derivat din Exception.

    // Adaugam stringul la lista tipurilor Exception

    exceptionTree.Add(String.Join("-", h, 1, h.Length -

    1));

    }

    }

    // Sortam tipurile Exception in ordinea ierarhiei lor.

  • 7/27/2019 curs .NET 7.pdf

    20/27

    Curs 7 / Pagina 20 din 27

    20

    exceptionTree.Sort();

    // Afisam arborescenta Exception.

    foreach (String s in exceptionTree)

    {

    // Pentru acest tip Exception,

    // separam tipul de baza sa.

    String[] x = s.Split(-);

    // Indentam pe baza numarului de tipuri de baza.

    Console.WriteLine(

    new String( , 3 * x.Length) + x[x.Length - 1]);

    }

    // Afisam starea finala a tipului considerat.

    Console.WriteLine("\n> Of {0} types, {1} are " +

    "derived from System.Exception.",

    totalTypes, totalExceptionTypes);

    Console.ReadLine();

    }

    static void LoadAssemblies()

    {

    String[] assemblies = {

    "System, PublicKeyToken={0}",

    "System.Data, PublicKeyToken={0}",

    "System.Design, PublicKeyToken={1}",

    "System.DirectoryServices, PublicKeyToken={1}",

    "System.Drawing, PublicKeyToken={1}",

    "System.Drawing.Design, PublicKeyToken={1}",

    "System.EnterpriseServices, PublicKeyToken={1}",

    "System.Management, PublicKeyToken={1}",

    "System.Messaging, PublicKeyToken={1}",

    "System.Runtime.Remoting, PublicKeyToken={0}","System.Security, PublicKeyToken={1}",

    "System.ServiceProcess, PublicKeyToken={1}",

    "System.Web, PublicKeyToken={1}",

    "System.Web.RegularExpressions, PublicKeyToken={1}",

    "System.Web.Services, PublicKeyToken={1}",

    "System.Windows.Forms, PublicKeyToken={0}",

    "System.Xml, PublicKeyToken={0}",

    };

    String EcmaPublicKeyToken = "b77a5c561934e089";

    String MSPublicKeyToken = "b03f5f7f11d50a3a";

    // Obtinem versiunea assembly ce contine System.Object.

    // Vom presupune aceeasi versiune

    // pentru toate celelate assemblies.

    Version version =

    typeof(System.Object).Assembly.GetName().Version;

    // Incarcam explicit assembly pe care vrem sa

    // aplicam reflection

    foreach (String a in assemblies)

    {

    String AssemblyIdentity =

  • 7/27/2019 curs .NET 7.pdf

    21/27

    Curs 7 / Pagina 21 din 27

    21

    String.Format(a, EcmaPublicKeyToken,

    MSPublicKeyToken) +

    ", Culture=neutral, Version=" + version;

    Assembly.Load(AssemblyIdentity);

    }

    }

    }

    Rezultatul este:

    System.ApplicationException

    System.Reflection.InvalidFilterCriteriaException

    System.Reflection.TargetException

    System.Reflection.TargetInvocationException

    System.Reflection.TargetParameterCountException

    System.IO.IsolatedStorage.IsolatedStorageException

    System.Runtime.Remoting.MetadataServices.SUDSGeneratorException

    System.Runtime.Remoting.MetadataServices.SUDSParserException

    System.SystemException

    System.AppDomainUnloadedException

    System.ArgumentExceptionSystem.ArgumentNullException

    System.ArgumentOutOfRangeException

    System.ComponentModel.InvalidEnumArgumentException

    System.DuplicateWaitObjectException

    System.ArithmeticException

    System.DivideByZeroException

    System.NotFiniteNumberException

    System.OverflowException

    System.ArrayTypeMismatchException

    System.BadImageFormatException

    System.CannotUnloadAppDomainException

    System.ComponentModel.Design.Serialization.CodeDomSerializerExceptionSystem.ComponentModel.LicenseException

    System.ComponentModel.WarningException

    System.Configuration.ConfigurationException

    System.ContextMarshalException

    System.Data.DataException

    System.Data.ConstraintException

    System.Data.DeletedRowInaccessibleExceptionSystem.Data.DuplicateNameException

    System.Data.InRowChangingEventException

    System.Data.InvalidConstraintException

    System.Data.InvalidExpressionException

    System.Data.EvaluateException

    System.Data.SyntaxErrorException

    System.Data.MissingPrimaryKeyException

    System.Data.NoNullAllowedException

    System.Data.ReadOnlyException

    System.Data.RowNotInTableException

    System.Data.StrongTypingException

    System.Data.TypedDataSetGeneratorException

  • 7/27/2019 curs .NET 7.pdf

    22/27

    Curs 7 / Pagina 22 din 27

    22

    System.Data.VersionNotFoundException

    System.Data.DBConcurrencyException

    System.Data.Odbc.OdbcException

    System.Data.SqlClient.SqlException

    System.Data.SqlTypes.SqlTypeException

    System.Data.SqlTypes.SqlNullValueException

    System.Data.SqlTypes.SqlTruncateExceptionSystem.Drawing.Printing.InvalidPrinterException

    System.EnterpriseServices.RegistrationException

    System.EnterpriseServices.ServicedComponentException

    System.ExecutionEngineException

    System.FormatException

    System.Net.CookieException

    System.Reflection.CustomAttributeFormatException

    System.UriFormatException

    System.IndexOutOfRangeException

    System.InvalidCastException

    System.InvalidOperationException

    System.Net.ProtocolViolationExceptionSystem.Net.WebException

    System.ObjectDisposedException

    System.InvalidProgramException

    System.IO.InternalBufferOverflowException

    System.IO.IOException

    System.IO.DirectoryNotFoundException

    System.IO.EndOfStreamException

    System.IO.FileLoadException

    System.IO.FileNotFoundException

    System.IO.PathTooLongException

    System.Management.ManagementException

    System.MemberAccessException

    System.FieldAccessException

    System.MethodAccessException

    System.MissingMemberException

    System.MissingFieldException

    System.MissingMethodException

    System.MulticastNotSupportedException

    System.NotImplementedException

    System.NotSupportedException

    System.PlatformNotSupportedException

    System.NullReferenceException

    System.OutOfMemoryExceptionSystem.RankException

    System.Reflection.AmbiguousMatchException

    System.Reflection.ReflectionTypeLoadException

    System.Resources.MissingManifestResourceException

    System.Runtime.InteropServices.ExternalException

    System.ComponentModel.Design.CheckoutException

    System.ComponentModel.Win32Exception

    System.Net.Sockets.SocketException

  • 7/27/2019 curs .NET 7.pdf

    23/27

    Curs 7 / Pagina 23 din 27

    23

    System.Data.OleDb.OleDbException

    System.Messaging.MessageQueueException

    System.Runtime.InteropServices.COMException

    System.Runtime.InteropServices.SEHException

    System.Web.HttpException

    System.Web.HttpCompileException

    System.Web.HttpParseExceptionSystem.Web.HttpRequestValidationException

    System.Web.HttpUnhandledException

    System.Runtime.InteropServices.InvalidComObjectException

    System.Runtime.InteropServices.InvalidOleVariantTypeException

    System.Runtime.InteropServices.MarshalDirectiveException

    System.Runtime.InteropServices.SafeArrayRankMismatchException

    System.Runtime.InteropServices.SafeArrayTypeMismatchException

    System.Runtime.Remoting.RemotingException

    System.Runtime.Remoting.RemotingTimeoutException

    System.Runtime.Remoting.ServerException

    System.Runtime.Serialization.SerializationException

    System.Security.Cryptography.CryptographicExceptionSystem.Security.Cryptography.CryptographicUnexpectedOperationException

    System.Security.Policy.PolicyException

    System.Security.SecurityException

    System.Security.VerificationException

    System.Security.XmlSyntaxException

    System.ServiceProcess.TimeoutException

    System.StackOverflowException

    System.Threading.SynchronizationLockException

    System.Threading.ThreadAbortException

    System.Threading.ThreadInterruptedException

    System.Threading.ThreadStateException

    System.TypeInitializationException

    System.TypeLoadException

    System.DllNotFoundException

    System.EntryPointNotFoundException

    System.TypeUnloadedException

    System.UnauthorizedAccessException

    System.Web.Services.Protocols.SoapException

    System.Web.Services.Protocols.SoapHeaderException

    System.Xml.Schema.XmlSchemaException

    System.Xml.XmlException

    System.Xml.XPath.XPathException

    System.Xml.Xsl.XsltExceptionSystem.Xml.Xsl.XsltCompileException

    Of 7281 types, 135 are derived from System.Exception.

    Explicatie asupra codului:String[] assemblies = {

    "System, PublicKeyToken={0}",

    "System.Data, PublicKeyToken={0}",

    "System.Design, PublicKeyToken={1}",

  • 7/27/2019 curs .NET 7.pdf

    24/27

    Curs 7 / Pagina 24 din 27

    24

    "System.DirectoryServices, PublicKeyToken={1}",

    "System.Drawing, PublicKeyToken={1}",

    "System.Drawing.Design, PublicKeyToken={1}",

    "System.EnterpriseServices, PublicKeyToken={1}",

    ...

    Ideea construirii acestui string, se gaseste in algoritmul folosit pentru construirea identitatii

    unui assemblyforeach (String a in assemblies)

    {

    String AssemblyIdentity =

    String.Format(a, EcmaPublicKeyToken,

    MSPublicKeyToken) +

    ", Culture=neutral, Version=" + version;

    ...

    altfel spus stringul assemblies contine si specificatorii de format.

    Rezultatul executiei codului de mai sus este (partial) :

    assemblies = System, PublicKeyToken={0}

    AssemblyIdentity = System, PublicKeyToken=b77a5c561934e089, Culture=neutral,Version=1.0.5000.0

    assemblies = System.Data, PublicKeyToken={0}

    AssemblyIdentity = System.Data, PublicKeyToken=b77a5c561934e089, Culture=neutral,

    Version=1.0.5000.0

    assemblies = System.Design, PublicKeyToken={1}

    AssemblyIdentity = System.Design, PublicKeyToken=b03f5f7f11d50a3a,

    Culture=neutral, Version=1.0.5000.0

    ...

    Cateva explicatii

    Metoda String.Split

    // string seperated by colons ';'string info = "mark;smith;123 csharp drive;toronto;canada";

    string[] arInfo = new string[4];

    // define which character is seperating fields

    char[] splitter = {';'};

    arInfo = info.Split(splitter);

    for(int x = 0; x < arInfo.Length; x++)

    {

    Console.WriteLine(arInfo[x] + "
    ");

    }

    Rezultatul este:

    mark

    smith

    123 csharp drive

    toronto

    canada

    Descarcarea explicita a unui assembly: descarcarea unui AppDomain

  • 7/27/2019 curs .NET 7.pdf

    25/27

    Curs 7 / Pagina 25 din 27

    25

    CLR nu suporta abilitatea de a descarca un assebly. In loc de aceasta trebuie sa descarcam

    un AppDomain ce are ca efect descarcarea tuturor assemblies din cadrul acestuia.

    Descarcarea unui AppDomain se face apeland metoda Unload, ce are drept parametru o

    refrerinta la un AppDomain.

    Important : Assembly care sunt incarcati intr-un AppDomain neutral nu pot fi descarcati

    niciodata. Un AppDomain neutral este descarcat cand procesul se termina.

    Exemplu de creare a unui AppDomain, transfer de date prin referinta in afara AppDomain.

    using System;

    using System.Reflection;

    using System.Threading;

    class App

    {

    static void Main()

    {

    // Creaza un AppDomain nou.

    AppDomain ad =

    AppDomain.CreateDomain("MyNewAppDomain", null, null);

    // Creaza un obiect MarshalByRef in noul AppDomain

    MarshalByRefType mbrt = (MarshalByRefType)ad.CreateInstanceAndUnwrap(

    Assembly.GetCallingAssembly().FullName,

    "MarshalByRefType");

    // Apeleaza o metoda pe acest obiect.

    // Proxy redirecteaza apelul catre alt AppDomain

    mbrt.SomeMethod(Thread.GetDomain().FriendlyName);

    // Am terminat cu acest AppDomain.// Il descarcam si implicit toate assemblies

    // pe care le contine.

    AppDomain.Unload(ad);

    // Incercam sa apelam o metoda pe un alt obiect

    // din AppDomain ce a fost descarcat.

    // Din acest motiv se va lansa o exceptie.

    try

    {

    mbrt.SomeMethod(Thread.GetDomain().FriendlyName);

    // Urmatoarea linie nu va fi afisata.Console.WriteLine(

    "Called SomeMethod on object in other AppDomain.\n" +

    "This shouldnt happen.");

    }

    catch (AppDomainUnloadedException)

    {

    // Am prins exceptia si o tratam.

    Console.WriteLine(

  • 7/27/2019 curs .NET 7.pdf

    26/27

    Curs 7 / Pagina 26 din 27

    26

    "Fail to call SomeMethod on object in other

    AppDomain.\n" +

    "This should happen.");

    }

    Console.ReadLine();

    }

    }

    // Un tip derivat din MarshalByRefObject.

    class MarshalByRefType : MarshalByRefObject

    {

    // Aceasta metoda de instanta poate fi apelata via proxy.

    public void SomeMethod(String sourceAppDomain)

    {

    // Afisam numele AppDomain apelat si al AppDomain curent.

    // Firul aplicatiei a facut tranzitia intre AppDomain.

    Console.WriteLine(

    "Code from the {0} AppDomain\n" +

    "called into the {1} AppDomain.",

    sourceAppDomain, Thread.GetDomain().FriendlyName);}

    }

    Iesirea este:

    Code from the 'p7_appdomain.exe' AppDomain

    called into the 'MyNewAppDomain' AppDomain.

    Fail to call SomeMethod on object in other AppDomain.

    This should happen.

    )#(

    )#,00-00

    #

    #

    &1 $$1%

    2-

    & 6%00'C)'D)

    $ ,-0%%%

    $/# ,0%

    %%%%

    #'$8)%

    ,-0

  • 7/27/2019 curs .NET 7.pdf

    27/27

    Curs 7 / Pagina 27 din 27

    %

    #'$8)%!

    / "!

    %2!

    E "0,

    "* #'$

    8)%

    1 "!!!.

    ! ",

    $

    $

    $ 202

    $ .

    ,

    $ "!

    $

    $ .0

    $

    $/# ,0%

    $1 ",

    .

    )

    )

    !


Recommended