如何将事件附加到动态对象或COM对象

时间:2013-03-26 06:23:47

标签: c# dynamic reflection com wmp

我认为this article与我有同样的问题。但是,我的案例没有可行的解决方案。

我在我的程序中使用Windows Media Player ActiveX。

出于某种原因,我不想添加它的引用并由IDE自动转换为AxHost。

我按ActivatorProgID

创建实例
protected const string WMP_PROG_ID = "WMPlayer.OCX.7";

private dynamic _wmp;

protected virtual bool init(){
    try{
        _wmp = Activator.CreateInstance(Type.GetTypeFromProgID(WMP_PROG_ID));
    }
    catch{ return false; }
    return true;
}

我试图通过Reflection执行此操作,但我发现dynamic适合我的情况。

每个属性和方法都可以正常工作,如下所示:

protected override bool setSpeed(float speed){
    try{
        _wmp.settings.rate = speed;
    }
    catch { return false; }
    return true;
}

protected override int getLength(){
    double res;
    try{
        res = _wmp.currentMedia.duration;
    }
    catch { return 0; }
    return (int)(res * 1000);
}

不幸的是,当我想附加the article I indicated in the top这样的事件时,它就没有用了。

我的代码是这样的:

protected bool connectEvent(){
_wmp.StatusChange += new EventHandler(_wmp_StatusChange);
    return true;
}

protected void _wmp_StatusChange(object sender, EventArgs e){
    Console.WriteLine(_wmp.Status);
}

我已检查StatusChange的事件处理程序类型,它是EventHandler

这些代码汇编得很好,我可以加载一些音乐,播放,暂停,......做任何我喜欢的事情。

StatusChange事件从未触发过。

我试图在connectEvent设置一个断点。

_wmp.StatusChange += new EventHandler(...)运行时,IntelliTrace会向我提供一些信息。

这些信息是用Trad写的。中文,我认为这意味着:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:无法应用运算符“+ =”来键入System.Dynamic.DynamicObjectSystem.EventHandler

即使有一个例外,但就像我说的那样,编译通过了,一切仍然有效 - 除了我听不到事件。

那么,如何在动态对象_wmp中成功附加事件?

任何可能的解决方案(如Reflection)对我都很有用。

此外,在上述情况中,StatusChange的处理程序类型为EventHandler

但是如果我想处理PlayStateChange事件,如果我不添加wmp.dll的引用,则它是“未知句柄”。

我希望解决方案也适合这种情况。

提前感谢所有人的支持,请原谅我的英语不好。

1 个答案:

答案 0 :(得分:1)

将使用COM对象的程序从早期绑定调用到后期绑定调用的通用策略是首先将其写入早期绑定。 IntelliSense将帮助您陷入成功之中,确保您使用正确命名的方法,传递正确的参数,特别有助于您了解事件处理程序签名应该是什么样的。

产生这一部分测试代码:

    void testEarlyBound() {
        var wmp = new WMPLib.WindowsMediaPlayer();
        wmp.StatusChange += new WMPLib._WMPOCXEvents_StatusChangeEventHandler(wmp_StatusChange);
    }

    void wmp_StatusChange() {
        throw new NotImplementedException();
    }

由IntelliSense完全自动生成StatusChange事件处理程序赋值和方法体。注意事件处理程序的签名,它是一个EventHandler。只是一个返回void并且不带参数的方法,它匹配Action委托类型。现在,您可以很好地编写后期绑定版本,而不会出现无法识别的运行时异常:

    void testLateBound() {
        dynamic wmp = Activator.CreateInstance(Type.GetTypeFromProgID("WMPlayer.OCX"));
        wmp.StatusChange += new Action(wmp_StatusChange);
    }