3

我认为这篇文章和我有同样的问题。但是,我的情况没有可行的解决方案。

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

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

Activator我通过and创建实例ProgID

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);
}

不幸的是,当我想像我在顶部指出的文章那样附加事件时,它没有工作。

我的代码是这样的:

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 会给我一些信息。

这些信息是用繁体书写的。中文,我觉得意思是:

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

即使有一个例外,但就像我说的,编译通过了,一切仍然有效——除了我无法监听事件。

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

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

此外,在上述情况下,处理程序类型StatusChangeEventHandler.

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

我希望该解决方案也适用于这种情况。

提前感谢大家的支持,请原谅我的英语不好。

4

1 回答 1

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);
    }
于 2013-03-26T10:44:39.697 回答