【问题标题】:Win32com.client.dispatch Python call Equivalent in C#Win32com.client.dispatch Python 调用等价于 C#
【发布时间】:2017-11-13 15:00:51
【问题描述】:

我有一个供应商提供给我的第 3 方动态链接库。该库是面向对象的。我目前正在尝试从 .Net 或 C# 访问此库,但是,在尝试调用方法时,.Net 中没有可用的方法 对这些库的支持由使用 Python 的程序员提供。 这是给我的 Python 示例:

import win32com.client
OLSV = Win32com.client.Dispatch("LsvEmu.LsvEmulator")
OLSV.BaseUnit

这是我在 C# 中尝试过的

using System;
using LsvComLib;
using System.Reflection;
using System.Reflection.Emit;
using LsvEmuLib;


namespace LsvDemo
{
    class Program
    {
        static void TestEmu()
        {
           //LsvEmu should include Connect, and ConnectEx methods
            var lsvEmu = new LsvEmulator();
           //EmulationMode is a property, and all that is available other 
            than ToString, etc
            Console.WriteLine(lsvEmu.EmulationMode);

            //Attempt to use reflection to find a Dispatch equivalent in C#
            Type mytype = (typeof(LsvEmulator));
            //public
            //No further methods found
            MethodInfo[] myArrayMethodInfo = mytype.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            DisplayMethodInfo(myArrayMethodInfo);

            //private
            //No further methods found
            MethodInfo[] myArrayMethodInfo1 = mytype.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            // Display information for all methods.
            DisplayMethodInfo(myArrayMethodInfo1);  
        }
}

什么是 Python Dispatch 调用的适当等价物? 此外,为什么无法通过反射获得预期的方法? 看来这个软件供应商可能无法访问所有原始源代码,所以我不确定他们能提供多少帮助。该库旨在模拟他们提供给我们的另一个库,该库对他们的设备进行以太网调用。如果由于实施不佳而导致通过反射显示的可用方法不足,我们可以构建自己的模拟器。

【问题讨论】:

  • C#了解不多,但是Python的Dispatch只是winIDispatch接口的一个实现。由于CreateObject 功能,它在VB 世界中也很有名。对于您的C# 实施,请尝试dynamic OLSV = Activator.CreateInstance(Type.GetTypeFromProgID("LsvEmu.LsvEmulator");object OLSV = Interaction.CreateObject("LsvEmu.LsvEmulator");
  • 谢谢!您是否对在 Visual Studio 开发环境之外使用此类调用有任何建议?例如,如果我在不同的环境(如 Labview)中使用 .Net 框架,则创建 dll 的实例会失败,因为它没有注册、不受管理,并且不能像在 CreateInstance 中那样按名称调用。使用 GetType 时有没有办法引用磁盘上的 dll 位置?
  • 如你所说,这个dll在系统中未注册。据我所知-如果你想使用这个接口,你应该注册它,因为Dispatch(<magic-word)CreateObject(<magic-word>) 中的magic-wordProgID(可以在注册表HKEY_CLASSES_ROOT\CLSID\<GUID>\ProgID 中找到注册)。
  • 任何人都可以解决这个问题,因为我正在实施类似的东西

标签: c# python dll dispatch


【解决方案1】:

我最近使用 .net core 2 及更高版本中的内置 COM 支持为类似情况实施了一个 .net 解决方案。此解决方案无需注册。你仍然有弄清楚你得到的数据类型是什么的问题,但是objectdynamic 类型可以帮助你。

因此,相当于 Python Dispatch 将是两行。

Type type = Type.GetTypeFromProgID("LsvEmu.LsvEmulator");
object inst = Activator.CreateInstance(type);

现在你有了应用方法的程序和接口。要从中获取属性,您可以使用 Bindingflag.GetProperty 调用 InvokeMember()

object result = (object)type.InvokeMember("BaseUnit", BindingFlags.GetProperty, null, inst, null);

Console.WriteLine(result);

要应用方法,您可以使用 BindingFlags.InvokeMethod 调用相同的 InvokeMember 函数,并将可选方法参数添加到最后一个参数,如下所示:

object result = (object)type.InvokeMember("ToString", BindingFlags.InvokeMethod, null, inst, new object[]{ "string" });

留意 .net core 3.0,它宣传原生支持动态方法调用,就像您在 Python https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0#interop-improvements 中看到的那样

【讨论】:

    猜你喜欢
    • 2021-01-08
    • 2012-05-11
    • 2011-11-25
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多