【问题标题】:How to access class of dynamically loaded clr / cli library in C#如何在 C# 中访问动态加载的 clr / cli 库的类
【发布时间】:2017-05-24 08:18:32
【问题描述】:

我是 clr / cli 和 C# 的新手。我的 C# 项目中有一个 clr / cli 库。我想动态加载它并在 C# 中访问其类的功能。有人可以提供一些例子或正确的方法吗?

这是我在 Clr/cli 库中的类声明头文件

namespace ManagedLibDarkClient {

       public ref class AccountHandler
       {
       public:
              AccountHandler()
              {

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

请在下面找到我尝试访问它的 C# 类的函数:--

        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");
}
}

在此示例中,我面临 2 个问题:- 1- LoadFile 挂起并且没有返回任何东西。 2- 我不知道如何获取我的 clr / cli 函数的返回值。

在这里,我想再提一件事。如果我静态链接它们,我可以访问 clr / cli。但我必须动态加载它。这对我来说是至关重要的要求。

【问题讨论】:

  • 听起来好像有死锁。如果你在你的 DllMain 中设置一个断点,它会被击中吗?如果您逐步完成,DllMain 是否完成?如果您让它运行直到挂起然后暂停执行,您的任何(本机)代码是否在堆栈(该进程中的任何线程)上?

标签: c# .net clr managed-c++


【解决方案1】:

首先,关于加载问题,请检查工作目录中是否存在 C++/CLI 库的所有本机依赖项 (dll)。
制作第三个包含接口的程序集

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

从您的 C++/CLI 和 C# 项目中添加对此程序集的引用
在 C++/CLI 中:

public ref class AccountHandler : public IAccountHandler
{
   public:
     AccountHandler()
     {

     }

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

然后,在 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
       }
    }
 }

我认为您不需要将 RegisterAccnt 设为静态。

【讨论】:

  • 嗨,西蒙,感谢您的快速回复和好榜样。但我认为我的问题是我无法使用 loadfile 加载托管 dll (clr / cli),因为它挂在那里。在这种情况下它也不起作用。您是否认为这是因为在我的 clr / cli dll 中,我同时使用了非托管和托管代码,而 loadfile 仅适用于纯托管代码?我们可以使用 PInvoke 访问 clr /cli dll 的类/函数吗?
  • 你得到什么错误?即使使用 Assembly.LoadFrom(...) 也会出现同样的错误吗?只是为了调查,您是否尝试将您的库添加为静态引用? PInvoke其实是用来访问原生库的,你有C++/CLI,可以认为是.Net程序集
  • 嗨 Simone,是的.. 它适用于静态库。问题是它只是挂在那里很长时间,而不是抛出一个很容易分析的异常。
  • HI SIMone,我创建了一个包装 C# 库。我在包装器库中将 clr/cli 库作为静态库引用,并从内部调用 managedLibDarkClient 的函数。现在在我的主 C# 库中,我尝试动态加载包装器库,但它给出了无法加载 ManagedLibDarkClient 库或其依赖项的错误。现在我的问题是系统如何静态加载但无法动态加载?
  • 这是一种非常奇怪的行为。您可以使用名为Fusion 的工具(它是.Net 框架的一部分)来记录加载错误。也许这会给你更多关于这个问题的信息。有时加载会失败,因为 C++/CLI 程序集依赖于本机 dll。在这种情况下,您可以引用它,但加载失败。
【解决方案2】:

您还可以添加引用,就像从已注册的 GAC 或并排程序集进行链接一样,并在加载失败时手动处理 ResolveAssembly 事件。查看this question的答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-10
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    相关资源
    最近更新 更多