【问题标题】:C# Reflection inconsistency with COM objectsC# 反射与 COM 对象不一致
【发布时间】:2016-08-28 08:17:58
【问题描述】:

在过去的几天里,我阅读了有关 C# 对 COM 对象的反射的所有内容,尝试了许多代码实验,并分析了示例代码以试图提高我的理解,我现在不得不承认我只是不知道的足够多,所以我向社区请求帮助。

我需要能够访问和更新包装为System._COM Object 的后期绑定 COM 对象的属性。

我尝试了所有标准的反射都没有成功,我使用IDispatch 浏览了一遍,但我不习惯使用所涉及的指针,所以我希望我错过了正常界面中一些非常简单的东西。我在 MSDN 上找到了确实展示了我需要做的事情的论文,但是所有示例都是用 C++ 编写的,这超出了我的想象。

如果有人能解释为什么以下简单的 C# 代码不能按预期工作,那将非常有帮助:

            try
        {
            // late binding:
            // localCB is a COM object (System._COMObject) created by Activator.CreateInstance() from 
            // the ProgID of a registered COM .DLL. 
            // 
            // The original .DLL has a string PROPERTY called 
            // "TESTEXTERNAL1". localCB has an IDispatch Interface.  The original COM .DLL has a separate Typelib,
            // and, although I did not register the typelib separately, I can see from OLEView on the COM object
            // that  the GUID for the typelib is included in it.

            // Here's the code that is puzzling me...
             var vv = localCB.GetType().InvokeMember("TESTEXTERNAL1", BindingFlags.GetProperty, 
                  null, localCB, null);
            string rt = vv.ToString();
            // works exactly as expected and returns the value of TESTEXTERNAL1 -  OK.

            // now try and update the SAME PROPERTY, on the SAME COM object...
            Parameters = new Object[1];
            Parameters[0] = "Hello, World!";
            localCB.GetType().InvokeMember("TESTEXTERNAL1", BindingFlags.SetProperty, 
                  null, localCB, Parameters);
            // throws an (inner) exception: HRESULT 0x8002003 DISP_E_MEMBERNOTFOUND !!!

        }
        catch (Exception xa)
        {
            string xam = xa.Message;
        }

期望已经找到并提供属性的对象能够更新相同的属性是不合理的吗?是否有一些我不知道的“替代更新”策略?

非常感谢您的帮助,

皮特。

更新:

应 Jon 的要求,这里是 OleView 的 sn-ps: (我不得不使用图片,因为 Oleview 不允许我剪切和粘贴,抱歉......)

OleView of the COM .DLL

OLEView typelib view

乔恩,我认为您已经正确地确定问题出在 setter 方法上。 DLL 是用 Fujitsu COBOL 编写的,并为标识为 PROPERTY 的字段提供了“幕后”的 GET 和 SET。从 C# 或 COBOL 访问 COM 组件,它工作正常,但是,如您所见,当我尝试使用反射访问它以进行 SET 时,它不起作用。因为我不熟悉使用反射,我怀疑我的语法是否正确,所以我试图让 SET 尽可能接近 GET。我想我需要在 COBOL 中生成我自己的 SET 方法(对于每个 PROPERTY),然后将我的“BindingFlags.SetProperty”更改为“BindingFlags.InvokeMember”。 (我在 BindingFlags 上做了功课,发现如果您指定“SetProperty”,它会自动暗示您提到的其他 2 个标志。)

我认为这一切的关键在于认识到问题出在 Fujitsu *COM Class SET 上,而您有经验的眼睛才能看到这一点。非常感谢。如果您在看到 OLEView 后有任何其他 cmets,或者可以建议任何替代方法来设置属性,我会非常感兴趣。 (我不期待必须为每个属性生成 SETter 方法;它带有蛮力的味道...... :-))

再次感谢,

皮特。

【问题讨论】:

  • 当您复制/粘贴在 OleView 输出中找到的属性声明时,这将更容易准确回答 很多。第一个解释是该属性没有设置器。下一个是一个属性可以有两个不同的设置器(put 和 putref),用 BindingFlags.PutDispProperty 和 BindingFlags.PutRefDispProperty 来区分。
  • 乔恩,感谢您的评论。我现在在另一台机器上,但明天我会用 OLEView 的属性描述更新帖子。所以发布的更新语法可以吗?我会对你提到的绑定标志做一些功课。
  • 我向 HansPassant 表示由衷的歉意。我误读了评论的海报(在 StackOverflow 和其他地方梳理了几天的东西......),并认为是 Jon Skeet。非常非常抱歉汉斯,非常感谢您提供的帮助。
  • @StephenKing - 斯蒂芬,您的编辑删除了一个句子,该句子准确地说明了我正在尝试做的事情。这对任何试图帮助我的人来说都是有用的。我从事编辑和校对工作超过 40 年。

标签: c# reflection com oleview


【解决方案1】:

汉斯是对的。问题出在 setter 方法上。我已经编写了代码来为每个属性生成一个设置器,回到原始的 COBOL COM 组件中。它并不像我想象的那么乏味或丑陋(每个属性大约 7 行 COBOL),现在一切都运行良好。非常感谢社区,特别是 Hans Passant 的支持。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 2013-03-23
    • 1970-01-01
    • 2010-11-12
    相关资源
    最近更新 更多