none
Dynamically load user controls from a DLL file in C# .net RRS feed

  • Frage

  • Hello,

    I'm writing an main interface application that needs to interact with different solutions base on the user needs so I have been reading a lot of blogs about how to dynamially load controls from DLL files but I have not been able to figure the porper code to make my application to work, most of the examples that I have faoud by now are for web applications so I think that could be one of the reasons I have not been able to find out the solution so the last code that I have used is:

     

    string dll_Directory = "c:\\my.dll";

            FileInfo fi = new FileInfo(dll_Directory);

            BinaryReader br = new BinaryReader(File.Open(dll_Directory, FileMode.Open));

            byte[] data = br.ReadBytes((int)fi.Length);

            br.Close();            

     

            Assembly assembly = Assembly.Load(data);

            string control_to_load = "UserControl"; //My DLL control name

            Type type = assembly.GetType(control_to_load);

            object control = Activator.CreateInstance(type);

            BindingFlags bflags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

     

            Object obj = type.InvokeMember(UserControl, bflags | BindingFlags.CreateInstance, null, null, null);

            System.Windows.Forms.Control c = (Control)obj;

            Group_Product_Interface.Controls.Add(c);

     

    But what I see is that the type is always null.

     

    I woudl be great is some one can give a suggestion of how to fix the code.

     

    Thanks. Zule_74

    Freitag, 10. Juni 2011 22:04

Antworten

  • Hi,

    I would like to point out a couple of things to begin with;

    • A plugin architecture typically utilizes a "base" class, or it can be an interface, that is known by your system at design time.
    • If using a "base" class, it typically is marked abstract.

    Despite the MANY examples on how to do this one can find by searching, one can easily apply the techniques to ASP.NET, WinForms, or any other .NET application. It can be boiled down to a couple of simple steps.

    Before I get to those steps, I have a couple questions:

    • How are you searching for your type based on a string? Did you use the correct assembly-qualified name? This means you would have to know the exact name of the "user controls" type at runtime (not very likely if someone inherited your "base" class). The Assembly.GetType method requires the Assembly.FullName, which is better explained by the AssemblyName class, that you are searching for in that module. It returns null if it can't find that type.
    • Are you able to create a "base" class to expose for the plugin architecture that can be referenced by your application? This greatly simplifies the process of loading custom plugins.

    I am going to assume you could define a "base" class in your project and expose that as the Type a 3rd party would need to implement. For this example, I am going to use System.Windows.Forms.UserControl as an example, but it could be a custom class you defined instead. I have a separate dll which defines a couple of user controls that will be late-bound (or dynamically created) and added to a FlowLayoutPanel on my form:

        private void LoadPlugins(string pluginPath)
        {
          List<System.Windows.Forms.UserControl> controls = new List<UserControl>();
    
          Assembly plugin = Assembly.LoadFrom(pluginPath);
    
          Type[] types = plugin.GetTypes();
    
          foreach (Type t in types)
          {
            if (typeof(UserControl).IsAssignableFrom(t))
            {
              UserControl control = (UserControl)Activator.CreateInstance(t);
    
              controls.Add(control);
            }
          }
    
          this.flowLayoutPanel1.Controls.AddRange(controls.ToArray());
        }
    

    Note, the Type.IsAssignableFrom method can be used to check if the Type is derived from your "base" class. If it is, then after creating a new instance it is added to the controls collection to be placed in the panel.

    HTH


    -Scosby
    Microsoft Community Contributor
    • Als Antwort vorgeschlagen Kris444 Sonntag, 12. Juni 2011 02:14
    • Als Antwort markiert Zule_74 Montag, 13. Juni 2011 22:47
    Samstag, 11. Juni 2011 00:15

Alle Antworten

  • Hi,

    I would like to point out a couple of things to begin with;

    • A plugin architecture typically utilizes a "base" class, or it can be an interface, that is known by your system at design time.
    • If using a "base" class, it typically is marked abstract.

    Despite the MANY examples on how to do this one can find by searching, one can easily apply the techniques to ASP.NET, WinForms, or any other .NET application. It can be boiled down to a couple of simple steps.

    Before I get to those steps, I have a couple questions:

    • How are you searching for your type based on a string? Did you use the correct assembly-qualified name? This means you would have to know the exact name of the "user controls" type at runtime (not very likely if someone inherited your "base" class). The Assembly.GetType method requires the Assembly.FullName, which is better explained by the AssemblyName class, that you are searching for in that module. It returns null if it can't find that type.
    • Are you able to create a "base" class to expose for the plugin architecture that can be referenced by your application? This greatly simplifies the process of loading custom plugins.

    I am going to assume you could define a "base" class in your project and expose that as the Type a 3rd party would need to implement. For this example, I am going to use System.Windows.Forms.UserControl as an example, but it could be a custom class you defined instead. I have a separate dll which defines a couple of user controls that will be late-bound (or dynamically created) and added to a FlowLayoutPanel on my form:

        private void LoadPlugins(string pluginPath)
        {
          List<System.Windows.Forms.UserControl> controls = new List<UserControl>();
    
          Assembly plugin = Assembly.LoadFrom(pluginPath);
    
          Type[] types = plugin.GetTypes();
    
          foreach (Type t in types)
          {
            if (typeof(UserControl).IsAssignableFrom(t))
            {
              UserControl control = (UserControl)Activator.CreateInstance(t);
    
              controls.Add(control);
            }
          }
    
          this.flowLayoutPanel1.Controls.AddRange(controls.ToArray());
        }
    

    Note, the Type.IsAssignableFrom method can be used to check if the Type is derived from your "base" class. If it is, then after creating a new instance it is added to the controls collection to be placed in the panel.

    HTH


    -Scosby
    Microsoft Community Contributor
    • Als Antwort vorgeschlagen Kris444 Sonntag, 12. Juni 2011 02:14
    • Als Antwort markiert Zule_74 Montag, 13. Juni 2011 22:47
    Samstag, 11. Juni 2011 00:15
  • Scosby,

     

    Thanks a lot for your help I was able to make my application to work so my mistake is that when I was getting the type did not reallize it has to be an Array as it is getting all the different names from the dll and not just the control name that I wanted to acces.

     

    Thanks again.

    Zule_74

    Montag, 13. Juni 2011 22:50