diff --git a/Exemples.sln b/Exemples.sln index 8e8098b..57380bb 100644 --- a/Exemples.sln +++ b/Exemples.sln @@ -459,7 +459,20 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ex_008_005_pattern_matching EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ex_014_008_deconstruction", "ex_014_008_deconstruction\ex_014_008_deconstruction.csproj", "{33CE1C87-3C57-48B8-A96E-FBF048BE65B8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ex_016_006_local_functions", "ex_016_006_local_functions\ex_016_006_local_functions.csproj", "{C67D6972-67D5-4AB8-84FA-CF7F8C7BD3E6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ex_016_006_local_functions", "ex_016_006_local_functions\ex_016_006_local_functions.csproj", "{C67D6972-67D5-4AB8-84FA-CF7F8C7BD3E6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "chap036_Reflection", "chap036_Reflection", "{CC07C89A-B410-4112-8686-A297FC0D34A8}" + ProjectSection(SolutionItems) = preProject + ex_036_001_Reflection\README.md = ex_036_001_Reflection\README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Applications", "Applications", "{3DE71730-143F-4835-A6B3-E501910EA94C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ex_036_001_Mammifere", "ex_036_001_Reflection\Solution\MammifereDll\ex_036_001_Mammifere.csproj", "{08D87D16-A9ED-42BC-8AF5-31AF9999AEF2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ex_036_001_ChatChienOiseau", "ex_036_001_Reflection\Solution\ChatChienOiseauDll\ex_036_001_ChatChienOiseau.csproj", "{FAA3150B-7230-4578-8CC0-775EDE947E7D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ex_036_001_Reflection", "ex_036_001_Reflection\Solution\Applications\ex_036_001_Reflection.csproj", "{3F4AF8F0-63C2-4226-BA8C-3D9992EB59C5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1147,6 +1160,18 @@ Global {C67D6972-67D5-4AB8-84FA-CF7F8C7BD3E6}.Debug|Any CPU.Build.0 = Debug|Any CPU {C67D6972-67D5-4AB8-84FA-CF7F8C7BD3E6}.Release|Any CPU.ActiveCfg = Release|Any CPU {C67D6972-67D5-4AB8-84FA-CF7F8C7BD3E6}.Release|Any CPU.Build.0 = Release|Any CPU + {08D87D16-A9ED-42BC-8AF5-31AF9999AEF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08D87D16-A9ED-42BC-8AF5-31AF9999AEF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08D87D16-A9ED-42BC-8AF5-31AF9999AEF2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08D87D16-A9ED-42BC-8AF5-31AF9999AEF2}.Release|Any CPU.Build.0 = Release|Any CPU + {FAA3150B-7230-4578-8CC0-775EDE947E7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FAA3150B-7230-4578-8CC0-775EDE947E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FAA3150B-7230-4578-8CC0-775EDE947E7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FAA3150B-7230-4578-8CC0-775EDE947E7D}.Release|Any CPU.Build.0 = Release|Any CPU + {3F4AF8F0-63C2-4226-BA8C-3D9992EB59C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F4AF8F0-63C2-4226-BA8C-3D9992EB59C5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F4AF8F0-63C2-4226-BA8C-3D9992EB59C5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F4AF8F0-63C2-4226-BA8C-3D9992EB59C5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1370,6 +1395,11 @@ Global {D1C02BFB-DA1E-4E9C-8236-BF5CC3C23F06} = {F2776023-5053-4F3A-895B-149456580FAD} {33CE1C87-3C57-48B8-A96E-FBF048BE65B8} = {7B8E3B4B-5E02-460A-98B4-C948F6CD61F0} {C67D6972-67D5-4AB8-84FA-CF7F8C7BD3E6} = {3469E317-6219-492E-98CF-B291CC4F4577} + {CC07C89A-B410-4112-8686-A297FC0D34A8} = {7C341E9D-52D0-43EB-BE40-3807F4D86FA6} + {3DE71730-143F-4835-A6B3-E501910EA94C} = {CC07C89A-B410-4112-8686-A297FC0D34A8} + {08D87D16-A9ED-42BC-8AF5-31AF9999AEF2} = {CC07C89A-B410-4112-8686-A297FC0D34A8} + {FAA3150B-7230-4578-8CC0-775EDE947E7D} = {CC07C89A-B410-4112-8686-A297FC0D34A8} + {3F4AF8F0-63C2-4226-BA8C-3D9992EB59C5} = {3DE71730-143F-4835-A6B3-E501910EA94C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8D31C3AE-36FF-4667-A2A7-0E670245A59E} diff --git a/ex_036_001_Reflection/README.md b/ex_036_001_Reflection/README.md new file mode 100644 index 0000000..cfb381b --- /dev/null +++ b/ex_036_001_Reflection/README.md @@ -0,0 +1,57 @@ +## How to use reflection to explore an assembly? +or +## How to use reflection to dynamically add a plugin to an application? + +This sample is made of three projects. Be careful with the role and moreover, the links between each other. + +#### 1) ex_036_001_Mammifère.csproj +This assembly contains a **_Mammifère_** class with a simple **_Name_** property and compiles to a dll in the **_ex_036_001_Reflection\bin_** directory. +#### 2) ex_036_001_ChatChienOiseau.csproj +This assembly contains three classes: +- 2 of them are inheriting from **_Mammifère_** (**_Chat_** and **_Chien_**), +- the other one is not inheriting from **_Mammifère_** (**_Oiseau_**). + +Important: this assembly references the first one, and compiles to a dll into the **_ex_036_001_Reflection\plugin_** directory. +#### 3) Applications\ex_036_001_Reflection.csproj +This assembly compiles to an exe in the **_ex_036_001_Reflection\bin_** directory. It references the first assembly, but **_does not reference_** the second assembly. +- First, it parses the plugin folder and gets all files : +```` C# +DirectoryInfo folder = new DirectoryInfo(Directory.GetCurrentDirectory().ToString()+"..\\..\\..\\plugin\\");F +ileInfo[] files = folder.GetFiles(); +```` +- Next, it filters these files and launches an assembly analysis on .dll files only +```` C# +foreach (FileInfo file in files.Where(f => f.Extension.Equals(".dll"))) +{ + AnalyseDLL(file.FullName); +} +```` +- In this **_AnalyseDLL(string filePath)_** method, first, it loads the assembly: +```` C# +Assembly a = Assembly.LoadFile(filePath); +```` +- then, it gets all the exported types of this assembly (all public types): +```` C# +Type[] types = a.GetExportedTypes(); +```` +- for each type **_t_** in **_types_**, it then writes its name in the Console, and tests if it's a subclass of **_Animal.Mammifère_** +```` C# +Write(t.Name); + +if(t.GetTypeInfo().IsSubclassOf(typeof(Animal.Mammifère))) +{ + // +} +```` + + +Remember that this Console App does not reference the assembly where the classes **_Chat_**, **_Chien_** and **_Oiseau_** are defined. +It only references the first assembly with the **_Animal.Mammifère_** class, so +this is the only class it knows at compile-time. It _discovers_ the others by reflection. + +Now you can explore the types (if they are primitive, interfaces, abstract, delegate, generics ...) and their members (methods, properties...). +Have fun! + + + +_Marc Chevaldonné, 27th of may 2019_ diff --git a/ex_036_001_Reflection/Solution/Applications/Program.cs b/ex_036_001_Reflection/Solution/Applications/Program.cs new file mode 100644 index 0000000..3d0a964 --- /dev/null +++ b/ex_036_001_Reflection/Solution/Applications/Program.cs @@ -0,0 +1,75 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Reflection; +using Animal; +using System.Linq; +using static System.Console; + +namespace Reflection +{ + class Program + { + static void Main(string[] args) + { + //permet d'accéder au dossier courant (ici l'endroit où se trouve l'exécutable) + WriteLine(System.IO.Directory.GetCurrentDirectory()); + + DirectoryInfo folder = new DirectoryInfo(Directory.GetCurrentDirectory().ToString()+"..\\..\\..\\plugin\\"); + FileInfo[] files = folder.GetFiles(); + + foreach (FileInfo file in files.Where(f => f.Extension.Equals(".dll"))) + { + AnalyseDLL(file.FullName); + } + } + + static void AnalyseDLL(string filePath) + { + //chargement d'une dll dans ce dossier courant + Assembly a = Assembly.LoadFile(filePath); + + //on récupère tous les types contenus dans cette dll dans un tableau "types" + Type[] types = a.GetExportedTypes(); + + //pour chacun de ces types : + foreach (Type t in types) + { + //on écrit le nom du type (nom d'une classe par exemple) + Write(t.Name); + + //teste si le type dérive de Mammifère ou non + if(t.GetTypeInfo().IsSubclassOf(typeof(Animal.Mammifère))) + { + //si le type dérive de Mammifère, on écrit le nom du type Mammifère entre parenthèses + Write(" (" + t.GetTypeInfo().BaseType.Name + ")\n"); + + //on appelle le constructeur du type (chat ou chien par exemple) et on le référence à l'aide d'une + //référence sur un Mammifère (chat et chien dérivent de mammifère) + Mammifère bitxo = Activator.CreateInstance(t) as Mammifère; + + //on affiche à l'écran le membre mName du type concerné (minou pour chat, toutou pour chien) + WriteLine(" je m'appelle : " + bitxo.Name); + } + else + { + //si le type ne dérive pas de Mammifère, alors on le dit + WriteLine(" ne dérive pas de Animal.Mammifère"); + } + WriteLine(); + } + } + } +} diff --git a/ex_036_001_Reflection/Solution/Applications/ex_036_001_Reflection.csproj b/ex_036_001_Reflection/Solution/Applications/ex_036_001_Reflection.csproj new file mode 100644 index 0000000..4973e3f --- /dev/null +++ b/ex_036_001_Reflection/Solution/Applications/ex_036_001_Reflection.csproj @@ -0,0 +1,40 @@ + + + + + + netcoreapp2.0 + ex_036_001_Reflection + Exe + ex_036_001_Reflection + 2.0.0 + $(PackageTargetFallback);dnxcore50 + false + false + false + + + + + + ../../bin + + + + ../../bin + + + + + + + \ No newline at end of file diff --git a/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chat.cs b/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chat.cs new file mode 100644 index 0000000..34c61f9 --- /dev/null +++ b/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chat.cs @@ -0,0 +1,25 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chat.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Animal +{ + public class Chat : Mammifère + { + public Chat() + { + Name = "minou"; + } + } +} diff --git a/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chien.cs b/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chien.cs new file mode 100644 index 0000000..c3e37de --- /dev/null +++ b/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chien.cs @@ -0,0 +1,25 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chien.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Animal +{ + public class Chien : Mammifère + { + public Chien() + { + Name = "toutou"; + } + } +} diff --git a/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Oiseau.cs b/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Oiseau.cs new file mode 100644 index 0000000..631836c --- /dev/null +++ b/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Oiseau.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Oiseau.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Animal +{ + public class Oiseau + { + public Oiseau() + { + Name = "cuicui"; + } + + public string Name + { + get; + protected set; + } + } +} diff --git a/ex_036_001_Reflection/Solution/ChatChienOiseauDll/ex_036_001_ChatChienOiseau.csproj b/ex_036_001_Reflection/Solution/ChatChienOiseauDll/ex_036_001_ChatChienOiseau.csproj new file mode 100644 index 0000000..7b97ad3 --- /dev/null +++ b/ex_036_001_Reflection/Solution/ChatChienOiseauDll/ex_036_001_ChatChienOiseau.csproj @@ -0,0 +1,40 @@ + + + + + + netcoreapp2.0 + ex_036_001_ChatChienOiseau + Library + ex_036_001_ChatChienOiseau + 2.0.0 + $(PackageTargetFallback);dnxcore50 + false + false + false + + + + + + ../../plugin + + + + ../../plugin + + + + + + + \ No newline at end of file diff --git a/ex_036_001_Reflection/Solution/MammifereDll/Mammifere.cs b/ex_036_001_Reflection/Solution/MammifereDll/Mammifere.cs new file mode 100644 index 0000000..efd4838 --- /dev/null +++ b/ex_036_001_Reflection/Solution/MammifereDll/Mammifere.cs @@ -0,0 +1,30 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Mammifere.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Animal +{ + public class Mammifère + { + public Mammifère() + { + } + + public string Name + { + get; + protected set; + } + } +} diff --git a/ex_036_001_Reflection/Solution/MammifereDll/ex_036_001_Mammifere.csproj b/ex_036_001_Reflection/Solution/MammifereDll/ex_036_001_Mammifere.csproj new file mode 100644 index 0000000..4ed28b5 --- /dev/null +++ b/ex_036_001_Reflection/Solution/MammifereDll/ex_036_001_Mammifere.csproj @@ -0,0 +1,38 @@ + + + + + + + netcoreapp2.0 + ex_036_001_Mammifere + Library + ex_036_001_Mammifere + 2.0.0 + $(PackageTargetFallback);dnxcore50 + false + false + false + + + + + + ../../bin + + + + ../../bin + + + +