C#与COM对象的反射不一致

时间:2016-08-28 08:17:58

标签: c# reflection com oleview

我花了最近几天阅读了有关COM对象的C#反射,在代码中尝试了许多实验,并分析示例代码以尝试提高我的理解的所有内容,我现在不得不承认我不会我知道的,所以我要求社区提供帮助。

我需要能够访问和更新包装为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的片段: (我不得不使用图像,因为Oleview不会让我剪切和粘贴,抱歉......)

OleView of the COM .DLL

OLEView typelib view

Jon,我认为你已经正确地确定了问题是使用setter方法。 DLL是用富士通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后有任何其他注释,或者可以建议任何替代方法以获得属性设置,我会非常感兴趣。 (我不期待必须为每个属性生成SETter方法;它有点蛮力......: - ))

再次感谢,

皮特。

1 个答案:

答案 0 :(得分:0)

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