locked
How to plug-in a dll into a project? RRS feed

  • Question

  • First question: How to plug-in a dll into a project?

    I would like to add a dll into a project but without re-compiling the project.

    Let’s say I have the project “Inventory” which has 3 dlls for now and planning to add more.

    The dlls have names such as CategoryA.dll, CategoryB.dll and CategoryC.dll. The dlls have used interface ICategory. The interface has methods Calc() and Report().

    To make some inventory calculations and print reports I need to use a specific dll by its name.

    Here is my second question: How to call corresponding dll’s method?

     

    If you have any recommendations or suggestions it would be good too. 

    Tuesday, January 5, 2010 5:03 AM

Answers

  • You can load the assembly dynamically and invoke its public methods. For example let's assume we have a dll that has an Add method that we want to use.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Assembly assembly = Assembly.LoadFrom(@"C:\Documents and Settings\john.grove\MyMath.dll");
                Type mathUtility = assembly.GetType("MyMathUtilty");
                Object theInstance = Activator.CreateInstance(mathUtility);
                Int32 result = (Int32)mathUtility.InvokeMember("Add", BindingFlags.InvokeMethod, null, theInstance, new object[] { 56, 26 });
                Console.WriteLine("Dynamically invoking MyMathUtilty Add method");
                Console.WriteLine("56 + 26 = {0}", result);
                Console.WriteLine("");
    
                // get all public static methods of MyMathUtilty type
                MethodInfo[] methodInfos = mathUtility.GetMethods(BindingFlags.Public | BindingFlags.Static);
                Console.WriteLine("All public/static methods in MyMathUtilty");
                Console.WriteLine("-------------------------------------------------");
                for (Int32 i = 0; i < methodInfos.Count(); i++ )
                    Console.WriteLine("{0}.) {1}", i + 1, methodInfos[i].Name);
                Console.ReadLine();
            }
        }
    }
    

    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    • Marked as answer by Lucky7777 Tuesday, January 5, 2010 7:06 PM
    Tuesday, January 5, 2010 5:54 AM
  • Hi  lucky777  here the  way  to  make your  project  extendible
    private object InvokeMethod(string methodName, object[] pObj)
            {
    
                object result  = null;
                try
                {
                     //verify  if  the data manager exist  
                    if (File.Exists("c:\\ MyFolder\\categoryc.dll"))
                    {
    
                        //load the  assembly 
                        Assembly assemblyEngine = Assembly.LoadFrom("c:\\ MyFolder\\categoryc.dll");
                        // verify  if  there  is  a class that implement your interface 
                        foreach (Type aType in assemblyEngine.GetTypes())
                        {
                            
                            if (aType.GetInterface(typeof(ICategory).FullName) != null)
                            {   //create an  instance of the class  
                                object obj = assemblyEngine.CreateInstance(aType.Namespace + "." + aType.Name, true);
                                //retrieve  the informations  about the method  to invoke 
                                MethodInfo executeMethod = assemblyEngine.GetType(aType.Namespace + "." + aType.Name).GetMethod(methodName);
                                //try to execute the method  
                                if (pObj == null)
                                {
                                    result = executeMethod.Invoke(obj, null);
                                }
                                else
                                {    //pObj  is an array  of objects  
                                    result= executeMethod.Invoke(obj, pObj);
                                }
                                //if  the interface  was  found exit from  the for  
                                goto Finish;
                            }
                        }
    
                        //
                    }
                Finish:
    
                    return  result;
                }
    hope this can enlighten  u 
    A man's dreams are an index to his greatness
    • Marked as answer by Lucky7777 Tuesday, January 5, 2010 7:06 PM
    • Edited by BRAHIM kamel Thursday, January 7, 2010 7:26 AM backslash
    Tuesday, January 5, 2010 8:49 AM
  • If they all use the same interface, put that interface in a separate project.
    Add that project as a reference in each of your projects.

    Use Assembly.LoadFrom and CreateInstance to instantiate the object and cast it to the interface:

    Assembly assembly = Assembly.LoadFrom(myVariableFromLoadDialog);
    Type type = assembly.GetType("NameOfTheTypeIWant");
    ICategory theInstance = Activator.CreateInstance(type) as ICategory;
    if(theInstance == null)
        MessageBox.Show("That dll is not supported");
    
    theInstance.Calc();
    theInstance.Report();
    That should work if you always use the same type name (if not, loop over all the types to find which one implements ICategory).
    I omitted several checks.
    • Marked as answer by Lucky7777 Tuesday, January 5, 2010 7:06 PM
    Tuesday, January 5, 2010 3:37 PM

All replies

  • You can load the assembly dynamically and invoke its public methods. For example let's assume we have a dll that has an Add method that we want to use.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Assembly assembly = Assembly.LoadFrom(@"C:\Documents and Settings\john.grove\MyMath.dll");
                Type mathUtility = assembly.GetType("MyMathUtilty");
                Object theInstance = Activator.CreateInstance(mathUtility);
                Int32 result = (Int32)mathUtility.InvokeMember("Add", BindingFlags.InvokeMethod, null, theInstance, new object[] { 56, 26 });
                Console.WriteLine("Dynamically invoking MyMathUtilty Add method");
                Console.WriteLine("56 + 26 = {0}", result);
                Console.WriteLine("");
    
                // get all public static methods of MyMathUtilty type
                MethodInfo[] methodInfos = mathUtility.GetMethods(BindingFlags.Public | BindingFlags.Static);
                Console.WriteLine("All public/static methods in MyMathUtilty");
                Console.WriteLine("-------------------------------------------------");
                for (Int32 i = 0; i < methodInfos.Count(); i++ )
                    Console.WriteLine("{0}.) {1}", i + 1, methodInfos[i].Name);
                Console.ReadLine();
            }
        }
    }
    

    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    • Marked as answer by Lucky7777 Tuesday, January 5, 2010 7:06 PM
    Tuesday, January 5, 2010 5:54 AM
  • To plug-in a dll into your project either drag and drop it into "References" or right-click on References and click Add reference.

    After that add reference to the namespace(s):

    "using Namescape.Something"

    And that's it. You can now call all the classes/methods inside the import dlls.

    Thanks

    Bottom line, you will have to recompile whether you load the assembly dynamically or however you use the assembly.
    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    Tuesday, January 5, 2010 6:05 AM
  • Hi  lucky777  here the  way  to  make your  project  extendible
    private object InvokeMethod(string methodName, object[] pObj)
            {
    
                object result  = null;
                try
                {
                     //verify  if  the data manager exist  
                    if (File.Exists("c:\\ MyFolder\\categoryc.dll"))
                    {
    
                        //load the  assembly 
                        Assembly assemblyEngine = Assembly.LoadFrom("c:\\ MyFolder\\categoryc.dll");
                        // verify  if  there  is  a class that implement your interface 
                        foreach (Type aType in assemblyEngine.GetTypes())
                        {
                            
                            if (aType.GetInterface(typeof(ICategory).FullName) != null)
                            {   //create an  instance of the class  
                                object obj = assemblyEngine.CreateInstance(aType.Namespace + "." + aType.Name, true);
                                //retrieve  the informations  about the method  to invoke 
                                MethodInfo executeMethod = assemblyEngine.GetType(aType.Namespace + "." + aType.Name).GetMethod(methodName);
                                //try to execute the method  
                                if (pObj == null)
                                {
                                    result = executeMethod.Invoke(obj, null);
                                }
                                else
                                {    //pObj  is an array  of objects  
                                    result= executeMethod.Invoke(obj, pObj);
                                }
                                //if  the interface  was  found exit from  the for  
                                goto Finish;
                            }
                        }
    
                        //
                    }
                Finish:
    
                    return  result;
                }
    hope this can enlighten  u 
    A man's dreams are an index to his greatness
    • Marked as answer by Lucky7777 Tuesday, January 5, 2010 7:06 PM
    • Edited by BRAHIM kamel Thursday, January 7, 2010 7:26 AM backslash
    Tuesday, January 5, 2010 8:49 AM
  • If they all use the same interface, put that interface in a separate project.
    Add that project as a reference in each of your projects.

    Use Assembly.LoadFrom and CreateInstance to instantiate the object and cast it to the interface:

    Assembly assembly = Assembly.LoadFrom(myVariableFromLoadDialog);
    Type type = assembly.GetType("NameOfTheTypeIWant");
    ICategory theInstance = Activator.CreateInstance(type) as ICategory;
    if(theInstance == null)
        MessageBox.Show("That dll is not supported");
    
    theInstance.Calc();
    theInstance.Report();
    That should work if you always use the same type name (if not, loop over all the types to find which one implements ICategory).
    I omitted several checks.
    • Marked as answer by Lucky7777 Tuesday, January 5, 2010 7:06 PM
    Tuesday, January 5, 2010 3:37 PM
  • Hi John,

    MethodInfo[] methodInfos = mathUtility.GetMethods(BindingFlags.Public | BindingFlags.Static);

    how to get just public methods and properties?
    Tuesday, January 5, 2010 6:34 PM
  • I believe there is a GetFields method you can use.
    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    Tuesday, January 5, 2010 6:50 PM
  • Great!
    Thanks everybody! :) 
    Tuesday, January 5, 2010 7:06 PM