Plugins şi System.Reflection.Assembly
În sfârşit am găsit timp pentru a explica întrebarea de mai devreme: La ce este folositoare clasa Assembly.
Au fost mai multe răspunsuri la respectiva întrebare. Cel pe care îl urmăream eu era că această clasă este folosită pentru încărca plugin-uri într-o aplicaţie. Când am pus acea întrebare trebuie să recunosc că mă refeream strict la plugin-uri. Totuşi, am descoperit mai multe moduri în care se poate folosi această clasă.
Un Assembly este unitate de bază din care sunt alcătuite aplicaţiile .NET. Un Assembly conţine, pe lângă codul MSIL, şi o serie de alte informaţii care descriu codul conţinut. Folosind clasa Assembly se pot determina o serie de informaţii interesante legate de codul conţinut în respectivul fişier. Când spun informaţii interesante mă refer la: tipurile definite, modulele incluse în fişier şi aşa mai departe.
Nu am să prezint toate aceste funcţioanlităţii, pentru a vedea fiecare funcţionalitate în parte vă recomand să mergeţi pe site-ul MSDN ce tratează această clasă. Totuşi, am să vă spun de metoda ReflectionOnlyLoadFrom, metodă care poate fi utilă în momentul în care se doreşte doar investigarea tipurilor de date dintr-un Assembly, nu şi instanţierea lor - interesant, nu?
Revenind la titlul acestui post şi la legătura acestei clase cu proiectul Blue Spirit. După cum am spus aici şi aici acest proiect a fost gândit să fie modular. Acest lucru înseamnă că trebuia să folosesc plugin-uri. Pentru a folosi încărca plugin-urile, am folosit clasa Assembly pentru a determina ce tipuri sunt definite şi clasa Activator pentru a instanţia respectivele tipuri. Există şi posibilitatea de a folosi funcţia CreateInstance asociată cu clasa Assembly pentru a instanţia un obiect.
Pentru că au fost voci care au cerut să vadă cod
am să prezint mai jos codul folosit pentru a încărca plugin-uri în cadrul proiectului meu.
Înainte de a trece la cod, trebuie să fie un disclaimer: codul folosit de mai jos este prezentat aşa cum este şi nu oferă garanţii. Dacă prin rularea lui apar probleme la sistemul pe care a fost rulat, autorul (adică eu
) nu va fi făcut răspunzător pentru acest lucru. Eu folosesc acest cod în cadrul proiectului fără probleme, dar acest disclaimer este "just in case".
Ar mai trebui spus modul în care se implementează plugin-urile. Există o interfaţă care defineşte un comportament pentru respectivul plugin. Ceea ce trebuie să facă cel care crează plugin-ul este să preia interfaţa şi să ofere o implementare a comportamentului.
Codul este prezentat mai jos:
///
<summary>///
Incarca combobox-urile cu plugin-urile din foldere///
</summary>///
<param name="folder">Folder-ul din care incarcam</param>///
<param name="myCombo">Combobox-ul in care punem</param>///
<param name="myDataType">Tipul de date care se doreste sa fie incarcat din DLL</param>private
void LoadPlugins(string folder, ComboBox myCombo, Type myDataType){
DirectoryInfo myDir = new DirectoryInfo(folder);FileInfo[] myFiles = myDir.GetFiles("*.dll");foreach (FileInfo f in myFiles){ try{ Assembly myAssembly = Assembly.LoadFile(f.FullName); Type[] myClasses = myAssembly.GetTypes(); foreach (Type t in myClasses) {
//Determinam daca t implementeaza interfata ceruta.Type[] interfaces = t.GetInterfaces();foreach (Type myInterfaceType in interfaces){ if (myInterfaceType.Equals(myDataType)){ObjectHandle myObj = Activator.CreateInstanceFrom(f.FullName, t.ToString());myCombo.Items.Add(myObj.Unwrap());
}
}
}
}
catch (Exception exc){ System.Diagnostics.
Trace.WriteLine(string.Format("{0}: {1}", this, exc.Message)); }
}
}
În concluzie, pentru a determina ce conţine un assembly, încărcăm acel fişier într-o instanţă a clasei Assembly şi apelăm metode asupra instanţei pentru a obţine informaţiile necesare.
Sper că v-a fost de folos acest mini-articol.
Technorati tags: Tehnice, BlueSpirit