Search code examples
c#.netclrmanaged-c++

How to access class of dynamically loaded clr / cli library in C#


I am novice in clr / cli and C#. I have one clr / cli library in my C# project. I want to load it dynamically and access the function of its class in C# . Can some one provide some example or right way to doing it.

Here is My header file of class declaration in Clr / cli library

namespace ManagedLibDarkClient {

       public ref class AccountHandler
       {
       public:
              AccountHandler()
              {

              }
              static bool RegisterAccnt(String^ accountID, String^ authCode);
       };
}

Please find below the function of my C# class on which I have tried to access it:--

        private void RegisterWindow_ValidateEvent(object sender, ValidateEventArgs e)
        {
                Assembly assembly = Assembly.Loadfile("C:\\darkmailWindows\\darkmailwindows\\Dependencies\\ManagedLibDarkMail\\Lib\\ManagedLibDarkClient.dll");
                if (assembly != null)
                {
                    Type type = assembly.GetType("AccountHandler");
                    var obj = Activator.CreateInstance(type);
                    if (obj != null)
                    {
                        string[] args = { e.AccntInfo.AccntName, e.AccntInfo.AuthCode };
                        type.InvokeMember("RegisterAccnt", BindingFlags.Default | BindingFlags.InvokeMethod, null, obj, args);

                    }
                    else
                        MessageBox.Show("Unable to laod object");
                }
                else
                    MessageBox.Show("unable to load assembly");
}
}

Here in this example I am facing 2 issue :-- 1- LoadFile hangs and did not return any thing. 2- I dont know how to get return value of my clr / cli function.

Here I would like to mention one more thing. I can access clr / cli if I link them statically. But I have to load it dynamically. It is crucial requirement for me.


Solution

  • First af all, regarding the loading issue, check that all the native dependencies (dlls) of your C++/CLI library are present in the working directory.
    Make a third assembly containing an interface

    public interface IAccountHandler
    {
       bool RegisterAccnt(String accountID, String authCode);
    }
    

    Add a reference to this assembly from both your projects, C++/CLI and C#
    In C++/CLI:

    public ref class AccountHandler : public IAccountHandler
    {
       public:
         AccountHandler()
         {
    
         }
    
         bool RegisterAccnt(String^ accountID, String^ authCode);
    };
    

    Then, in C#:

    string filename = "C:\\darkmailWindows\\darkmailwindows\\Dependencies\\ManagedLibDarkMail\\Lib\\ManagedLibDarkClient.dll";
    
    Assembly asm = Assembly.LoadFrom(filename);
    
    foreach (Type t in asm.GetTypes())
    {
       if (t.GetInterfaces().Contains(typeof(IAccountHandler)))
       {
          try
          {
             IAccountHandler instance = (IAccountHandler)Activator.CreateInstance(t);
    
             if (instance != null)
             {
                 instance.RegisterAccnt(e.AccntInfo.AccntName, e.AccntInfo.AuthCode);                   
             }
           }
           catch(Exception ex)
           {
              //manage exception
           }
        }
     }
    

    I think you don't need to make RegisterAccnt static.