我认为this article与我有同样的问题。但是,我的案例没有可行的解决方案。
我在我的程序中使用Windows Media Player ActiveX。
出于某种原因,我不想添加它的引用并由IDE自动转换为AxHost。
我按Activator
和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);
}
不幸的是,当我想附加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.DynamicObject
和System.EventHandler
即使有一个例外,但就像我说的那样,编译通过了,一切仍然有效 - 除了我听不到事件。
那么,如何在动态对象_wmp
中成功附加事件?
任何可能的解决方案(如Reflection
)对我都很有用。
此外,在上述情况中,StatusChange
的处理程序类型为EventHandler
。
但是如果我想处理PlayStateChange
事件,如果我不添加wmp.dll的引用,则它是“未知句柄”。
我希望解决方案也适合这种情况。
提前感谢所有人的支持,请原谅我的英语不好。
答案 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);
}