4

我正在尝试将 COM 对象从 C# 代码传递给 Perl。
目前,我正在使用 PerlNET(PDK 9.4;ActiveState)包装我的 Perl 代码,并且我在 Perl 中定义了一个简单的子例程(+ 所需的 pod 声明)来将对象从 C# 传递到包装的 Perl 模块。

似乎我传递的对象没有被正确识别为 COM 对象。

一个例子:
在 C# (.NET 4.0) 中,ScriptControl 用于从用 VBScript 编写的文件中加载一个简单的类。

var host = new ScriptControl();
host.Language = "VBScript";
var text = File.ReadAllText("TestScript.vbs"); 
host.AddCode(text);

dynamic obj = host.Run("GetTestClass");

我得到的 ( obj) 是类型System.__ComObject。当我将它传递给我的 Perl/PerlNET 程序集并尝试Xyz()在 Perl 中调用方法时,我得到以下(运行时)异常:

Can't locate public method Xyz() for System.__ComObject

但是,如果我在 Perl 中或多或少地做同样的事情,它就可以工作。(在以下情况下,仅传递我的 .vbs 文件的内容作为参数。)我什至可以使用脚本控件:

sub UseScriptControl {
    my ($self, $text) = @_;
    my $script = Win32::OLE->new('ScriptControl');
    $script->{Language} = 'VBScript';
    $script->AddCode($text);
    my $obj = $script->Run('GetTestClass');

    $obj->Xyz();
}

现在,调用Xyz()工作obj正常(使用 Win32::OLE)。

在这两种情况下,我都使用:

use strict;
use Win32;
use Win32::OLE::Variant;

另一种方法:如果我准确指定要使用的重载以及要传递的类型,我可以通过使用类
来调用方法:InvokeMemberSystem.Type

use PerlNET qw(typeof);

typeof($obj)->InvokeMember("Xyz", 
    PerlNET::enum("System.Reflection.BindingFlags.InvokeMethod"), 
    PerlNET::null("System.Reflection.Binder"), 
    $obj, 
    "System.Object[]"->new());

使用这种方法意味着重写整个包装的 Perl 模块。并使用这种语法..

现在我想知道,通过将 PerlNET 与 COM 对象结合使用,我是否会同时失去 .NET 4.0 中 dynamic 关键字的优点和 Perl(使用 Win32::OLE)的动态特性。

似乎我首选的解决方案归结为某种模仿dynamicC#/.NET 4.0 中关键字行为的方式。

或者,更好的是,找到某种方法将传递的 COM 对象转换为可被识别为与Win32::OLE. 也许提取一些信息__ComObject以便将其正确识别为 COM 对象。

我必须补充一点,我也发布到了 PDK 讨论网站(但还没有得到任何回复): http: //community.activestate.com/node/18247
我也将它发布到 PerlMonks - 因为我不完全确定这更像是 Perl 还是 C#/.NET 问题: http ://www.perlmonks.org/?node_id=1146244

我将不胜感激任何帮助 - 或建议在哪里进一步寻找。

4

0 回答 0