System .__ ComObject的动态转换

时间:2014-10-06 11:12:36

标签: c# dynamic casting com type-conversion

是否可以将System .__ ComObject强制转换为某种类型,仅在运行时才知道? 我有以下代码

Type ComClassType = SomeDLLAssembly.GetType("ClassName");
dynamic comClassInstance = icf2.CreateInstanceLic(null, null, ComClassType.GUID, "License string");
//This will throw exception, because comClassInstance type is __ComObject and it does not contains ComClassMethod
comClassInstance.ComClassMethod();

当我将使用下面的代码时,它工作正常,但不幸的是我不能在我的代码中使用InvokeMember,因为它会非常复杂。

ComClassType.InvokeMember("ComClassMethod", BindingFlags.InvokeMethod, null, comClassInstance, null);

所以我想问一下,是否可以投出" comClassInstance" to" ComClassType"为了能够以这种方式调用方法comClassInstance.ComClassMethod();

4 个答案:

答案 0 :(得分:5)

  

仅在运行时才知道?

至少部分问题。在编译时知道类型时,只能使用强制转换。你不知道所以你不能写出演员表达。但它比那更深,你不知道运行时的类型。 __ComObject是RCW的低级包装器,它存储IDispatch接口指针。它没有说明您可以调用哪些方法以及可以使用哪些属性。

这是较低级别的输入,它是动态类型。这个术语的一般术语是后期绑定。这是另一种程序员编写的与代码接口的尝试调用方法。 C#团队长时间拒绝它,静态类型是语言的核心,迫使程序员使用Reflection。但不过,根据大众需求,他们在v4中添加了动态关键字,使得C#与Visual Basic保持一致,并始终支持它。您现在可以使用符号而不是将字符串传递给Reflection方法,而DLR会自动使用反射来进行调用。否则完全相同的编程工作,你必须知道字符串。

后期绑定的主要优点是它对版本控制具有弹性,这是第三方支持它的基本原因。但它的主要缺点是,如果你没有一本好的手册或者版本变化太多,那么你会得到一个讨厌的运行时异常,除了“它没有用”之外什么也不会告诉你。编译器无法帮助您正确完成,它不知道类型。 IntelliSense无法帮助您,它无法提供任何自动完成功能。只是在运行时爆炸,找出问题的唯一方法是翻阅(缺失)手册或与程序员交谈。

许多COM组件都支持早期和晚期绑定。您需要类型库来使用早期绑定,它是组件支持的接口和coclass的机器可读描述。它与.NET程序集中的元数据完全等效。并执行相同的角色,使用类型库,编译器现在可以检查您的代码,IntelliSense可以提供自动完成。

类型库通常嵌入在可执行文件(.dll或.exe)中,有时它作为单独的文件提供,.tlb和.olb是常见的扩展名。您可以使用Visual Studio的文件>打开>要查看可执行文件内部的文件,如果嵌入了类型库,您将看到TYPELIB节点。然后,您可以使用OleView.exe,文件>查看Typelib命令以查看其内容。并运行Tlbimp.exe以生成互操作库。

如果您找不到类型库并且没有合适的最新编程手册,那么只有电话可以帮助您。致电该组件的所有者或作者以获得帮助。

答案 1 :(得分:3)

调用COM对象的方法不需要强制转换。

C#dynamic可以用作(在调用之前不需要编写强制转换表达式)

public static void main(String[] args) throws FileNotFoundException, IOException {
        System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
        ChromeDriver browser = new ChromeDriver();  
        WebDriver driver = browser;
        driver.get("https://news.google.co.in/");
        driver.manage().timeouts().implicitlyWait(500, TimeUnit.SECONDS);

        JavascriptExecutor jse = (JavascriptExecutor) driver;
        Long clientHeight = (Long) jse.executeScript("return document.documentElement.clientHeight");
        Long scrollHeight = (Long) jse.executeScript("return document.documentElement.scrollHeight");
        int screens = 0, xAxis = 0, yAxis = clientHeight.intValue();
        String screenNames = "D:\\Screenshots\\Yash";
        for (screens = 0; ; screens++) {
            if (scrollHeight.intValue() - xAxis < clientHeight) {
                File crop = new File(screenNames + screens+".jpg");
                FileUtils.copyFile(browser.getScreenshotAs(OutputType.FILE), crop);                 

                BufferedImage image = ImageIO.read(new FileInputStream(crop));            
                int y_Axixs = scrollHeight.intValue() - xAxis;
                BufferedImage croppedImage = image.getSubimage(0, image.getHeight()-y_Axixs, image.getWidth(), y_Axixs);
                ImageIO.write(croppedImage, "jpg", crop);               
                break;
            }               

FileUtils.copyFile(browser.getScreenshotAs(OutputType.FILE), new File(screenNames + screens+".jpg")); 
 jse.executeScript("window.scrollBy("+ xAxis +", "+yAxis+")");

                jse.executeScript("var elems = window.document.getElementsByTagName('*');"                              
                        + "     for(i = 0; i < elems.length; i++) { "
                        + "         var elemStyle = window.getComputedStyle(elems[i], null);"
                        + "         if(elemStyle.getPropertyValue('position') == 'fixed' && elems[i].innerHTML.length != 0 ){"                                                                  
                        + "             elems[i].parentNode.removeChild(elems[i]); "                                
                        + "}}");    // Sticky Content Removes
                xAxis += yAxis;
        }
        driver.quit();
    }

OR

在vb.net中创建一个库项目(Option strict应为Off,Project属性)。在vb.net中完成与COM相关的所有内容,并在C#项目中添加对此的引用。

将实例类型声明为dynamic comClassInstance = Activator.CreateInstance(Type.GetTypeFromProgID("ClassName")); comClassInstance.ComClassMethod(); var result = comClassInstance.ComClassFMethod(param);

对COM组件进行Object调用,并将方法调用为CreateObject

comClassInstance.ComClassMethod()

答案 2 :(得分:0)

如果你的&#34; ClassName&#34; COM是可见的,您应该能够使用基本类型转换来转换返回的com对象。

Type ComClassType = SomeDLLAssembly.GetType("ClassName");
ClassName myInstance = (ClassName)icf2.CreateInstanceLic(null, null, ComClassType.GUID, "License string");
myInstance.ComClassMethod();

答案 3 :(得分:0)

我不完全确定这是你所追求的,如果是,你需要根据你创建实例的方式进行调整,因为我并没有真正关注icf2的来源。但是,如果您只是尝试清理大多数代码与COM对象交互的方式,那么一种方法是扩展dynamic解析过程。您可以通过继承DynamicObject并覆盖TryInvokeMember方法来实现此目的(您可以覆盖其他方法,但TryInvokeMember似乎是关键方法)。当动态调度程序无法找到方法时,可以在对象上调用此方法,以便您可以执行某些自定义解析。

所以,在基本层面(就像我跳过错误处理的所有好例子一样),你可以写一个这样的类:

public class ComWrapper : DynamicObject {
    Object _instance;
    Type _type;

    // Create + save type/instance information in constructor
    // You seem to do this differently, so you'd want to change this...
    public ComWrapper(Guid guid) {
        _type = Type.GetTypeFromCLSID(guid, true);
        _instance =  Activator.CreateInstance(_type, true);            
    }

    // Invoke requested method, passing in args and assigning return value
    // to result
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, 
                                         out object result) {
        result = _type.InvokeMember(binder.Name, 
                                    System.Reflection.BindingFlags.InvokeMethod, null,
                          _instance, args);

        return true;  // Return true to indicate it's been handled
    }
}

然后,基于an example which creates an instance of Word, then tells it to quit,您将使用上面的代码:

dynamic val = new ComWrapper(new Guid("{000209FF-0000-0000-C000-000000000046}"));

val.Quit(0, 0, false );

我认为动态类很可能已经做了类似于上面的内容,所以这可能不会解决你的问题。但是,它可能会让您更接近找到解决方案。例如,在不支持调度的COM对象上调用方法将通过InvokeMethod报告错误,但在通过动态实例调用时将报告Does not contain a definition