【问题标题】:Load DLL and create instances of interface implementations dynamically at runtime在运行时动态加载 DLL 并创建接口实现的实例
【发布时间】:2020-09-24 19:57:27
【问题描述】:

我有很多 DLL 连接器。每个 DLL 里面的方法太多了。但是每个 DLL 连接器都包含以下两种方法(byte[] Document = GetDocument(string, string, string); 和 byte[] Image = GetImage(string, string, string);)。

我想要做的是: 1- 在运行时选择 DLL 文件。 2-填写三个字符串。 3- 将三个字符串传递给插入的 DLL 中的方法(上面提到)以接收返回的文件。

我只是想知道如何调用 DLL 中的方法。

感谢任何帮助。

【问题讨论】:

    标签: c# dll load


    【解决方案1】:

    你必须使用反射(当然)。
    看看Assembly 类。

    你可以例如使用Assembly.LoadFileAssembly.LoadFrom 加载程序集。
    要激活包含在程序集中的类型以调用其成员,您可以使用Assembly.CreateInstance

    Assembly assembly = Assembly.LoadFile("C:\bin\runtime.dll");
    TypeInsideAssembly instanceOfTypeInsideAssembly = (TypeInsideAssembly) assembly.CreateInstance(typeOf(TypeInsideAssembly));
    instanceOfTypeInsideAssembly.InvokeMethod(params);
    

    如果构造函数需要参数,您可以使用适当的overloadCreateInstance(String, Boolean, BindingFlags, Binder, Object[], CultureInfo, Object[])

    示例

    以下通用示例使用反射创建位于指定程序集中的TBase 实例,需要一个无参数构造函数。 TBase 可以是类(基类)或接口。
    不是public 或未定义无参数构造函数的类型将被忽略。

    private IEnumerable<TBase> GetInstancesOf<TBase>(string assemblyFilePath)
    {
      var assembly = Assembly.LoadFile(assemblyFilePath);
    
      // Get all public types that are defined in this assembly
      Type[] publicTypes = assembly.GetExportedTypes();
    
      // Filter all public types in assembly and return only types...
      IEnumerable<TBase> documentProviders = publicTypes
    
        // ...that are not an interface (as we can't create instances of interfaces)...
        .Where(publicType => !publicType.IsInterface 
    
          // ...AND that are not an abstract class (as we can't create instances of abstract types)...
          && !publicType.IsAbstract 
    
          // ...AND that have a public parameterless constructor...
          && publicType.GetConstructor(Type.EmptyTypes) != null 
    
          // ...AND are a subtype of TBase. Note that TBase can be a base class or interface 
          && typeof(TBase).IsAssignableFrom(publicType))
    
        // Take each collected type and create an instance of those types
        .Select(concreteInterfaceType => assembly.CreateInstance(concreteInterfaceType.FullName))
    
        // Since CreateInstance() returns object, cast each created instance to the common subtype TBase
        .Cast<TBase>();
    
      return documentProviders;
    }
    

    用法

    private void HandleDocuments(string assemblyFilePath)
    {
      foreach (IClientMethods documentProvider in GetInstancesOf<IClientMethods>(assemblyFilePath))
      {        
        byte[] document = documentProvider.GetDocument(...);
      }
    }
    

    【讨论】:

    • 非常感谢您的回复。所以要在我的代码中使用它并调用这个方法: GetDocument(String,String,String) : Byte ` Assembly assembly = Assembly.LoadFile("C:\bin\runtime.dll"); byte[] instanceOfTypeInsideAssembly = (byte[])assembly.CreateInstance(GetDocument(byte[])); instanceOfTypeInsideAssembly.InvokeMethod("My Name", "My ID", "Phone Number");` 是否正确?
    • 变量、类型和方法名称只是您实际代码的占位符。在你的情况下,你可能会打电话给byte[] document = instanceOfTypeInsideAssembly.GetDocument(stringA, stringB, stringC)。你没有提供足够的细节。这就是为什么我的回答是笼统的。您必须创建定义 GetDocument 的类型的实例。
    • 在我的情况下,您需要哪些详细信息来帮助我?实际上是因为我读了很多关于它但不明白在我的情况下该怎么做。
    • 您只需要根据占位符的名称将占位符替换为值即可。定义GetDocument 的类型是什么?这种类型是否有一个你会调用的无参数构造函数?
    • 如何知道它的类型? ?? 是这个吗==> [Export(typeof(IClientMethods))] ?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 2020-06-25
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多