Late binding in C #

    Have you seen at least one C # project not using DLL? A serious non-modular project? In any case, sooner or later, this issue will be critical for you. For the rest, this article is not of interest, because only basic concepts are described here with an example of the implementation of reflection.

    In .NET, writing plugins is a simple task that can be accomplished with reflection. Reflection allows you to dynamically load assemblies, get information about methods, properties, events and fields of classes from assemblies, create new types and call methods at runtime. Classes and interfaces for reflection are in the System.Reflection namespace.
    To begin with, we will write two dll modules, in the classes of which we implement an interface common to each module and the main application.
    The interface will be as follows: Each module will assume the implementation of the someMethod method and the name property. The property will return the name of the module. The class of each plug-in (module) will implement the interface from Interdace.dll, which must be added to the plug-in references. When developing a plugin, we have only the interface necessary for implementation. Module 1 Module 2 So, the modules are ready. Let's start writing the main MainApp application. MainApp should track the appearance of new modules in a specific directory, the connection of those, the creation of module class objects and their conversion to the type of interface (also available in MainApp). Search: Here the path to the directory with plugins is declared as follows:
    1.  
    2. namespace Interface
    3. {
    4.   public interface Interface1
    5.   {
    6.     int someMethod(int a, int b);
    7.     string name { get; }
    8.   }
    9. }
    * This source code was highlighted with Source Code Highlighter.


    Интерфейс положим в Interface.dll. Эта библиотека будет общей для модулей и основного приложения. В нашем случае, модуль будет работоспособен, если в конечном итоге dll-ка модуля будет лежать в каталоге с Interdace.dll.






    1. using System;
    2. using System.Collections.Generic;
    3. using System.Text;
    4. using Interface;
    5.  
    6. namespace Plugin1
    7. {
    8.   public class pl1:Interface1
    9.   {
    10.     private string pl_name = "Произведение чисел";
    11.     public int someMethod(int a, int b)
    12.     {
    13.       return a * b;
    14.     }
    15.     public string name
    16.     {
    17.       get { return pl_name; }
    18.     }
    19.     public static string getStaticString()
    20.     {
    21.       return "I'm a string from static method of plugin 1 which has been called using invoke method";
    22.     }
    23.       
    24.   }
    25. }
    * This source code was highlighted with Source Code Highlighter.




    1. using System;
    2. using System.Collections.Generic;
    3. using System.Text;
    4. using Interface;
    5.  
    6. namespace Plugin2
    7. {
    8.   public class pl2 : Interface1
    9.   {
    10.     private string pl_name = "Сумма чисел";
    11.     public int someMethod(int a, int b)
    12.     {
    13.       return a + b;
    14.     }
    15.     public string name
    16.     {
    17.       get { return pl_name; }
    18.     }
    19.  
    20.     public string getNoneStaticString2()
    21.     {
    22.       return "I'm a string from none static method of plugin 2 which has been called using invoke method";
    23.     }
    24.  
    25.   }
    26. }
    * This source code was highlighted with Source Code Highlighter.





    1.     public void loadPlugins()
    2.     {
    3.  
    4.       string[] files = Directory.GetFiles(folder, "*.dll");
    5.       foreach (string file in files)
    6.       {
    7.         try
    8.         {
    9.           Assembly assembly = Assembly.LoadFile(file);
    10.           foreach (Type type in assembly.GetTypes())
    11.           {
    12.             Type iface = type.GetInterface("Interface.Interface1");
    13.  
    14.  
    15.             if (null != iface)
    16.             {
    17.               Interface.Interface1 obj = (Interface.Interface1)Activator.CreateInstance(type);
    18.               plugins.Add(obj);
    19.             }
    20.           }
    21.         }
    22.         catch (Exception e)
    23.         {
    24.         }
    25.       }
    26.  
    27.     }
    * This source code was highlighted with Source Code Highlighter.



    1. private readonly string folder = Directory.GetCurrentDirectory() + "\\dlls\\";
    * This source code was highlighted with Source Code Highlighter.


    Using the static LoadFile method of the Assembly class, we loaded the assembly by passing the assembly name to the method. The Activator class is a special class for instantiating types and obtaining references to remote objects. Using the CreateInstance method of the Activator class, we created a module class object by passing the class type of the created object to the method.
    By calling loadPlugins () when the application starts, we will dynamically load all the modules located in the dlls directory, in which the classes implement the desired interface.

    Next up is the call to the methods. By some condition, we select the module from which we are going to call the method. Here, the selection condition was a combo box. Accordingly, Plugin1.pl1.someMethod () or Plugin2.pl2.someMethod () is launched.
    1.         foreach (object pl in plugins)
    2.         {
    3.           if (((Interface.Interface1)pl).name.Equals(selected))
    4.           {
    5.             result = ((Interface.Interface1)pl).someMethod(a, b);
    6.           }
    7.         }
    * This source code was highlighted with Source Code Highlighter.




    But what about static methods? The interface cannot help to work with them. We will do the Invoke () method, passing the name. This invokes the static method of the plugin_2 class. Notice that we passed null as the first parameter to Invoke (). To invoke a non-static method using Invoke, you just need to pass the object containing the method. So, we dynamically loaded assemblies, created new types and called methods (including static ones) at runtime - in short, we tasted reflection. Sources are here PS I really hope that this article will find its audience and will be useful
    1.       Assembly asm = Assembly.LoadFile(folder + "\\Plugin1.dll");
    2.       Type classType = asm.GetType("Plugin1.pl1");
    3.       MethodInfo mi = classType.GetMethod("getStaticString");
    4.  
    5.       label2.Visible = true;
    6.       label2.Text = mi.Invoke(null, null).ToString();
    * This source code was highlighted with Source Code Highlighter.





    1. Assembly asm = Assembly.LoadFile(folder + "\\Plugin2.dll");
    2.       Type classType = asm.GetType("Plugin2.pl2");
    3.       object obj = Activator.CreateInstance(classType);
    4.       MethodInfo mi = classType.GetMethod("getNoneStaticString2");
    5.  
    6.       label3.Visible = true;
    7.       label3.Text = mi.Invoke(obj, null).ToString();
    * This source code was highlighted with Source Code Highlighter.







    Also popular now: