如何将事件附加到动态对象或COM对象 [英] How to attach event to dynamic object or COM object

查看:183
本文介绍了如何将事件附加到动态对象或COM对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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



我通过 Activator 和 ProgID

  protected const字符串WMP_PROG_ID =WMPlayer.OCX.7; 

私人动态_wmp;

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

我试图通过 Reflection ,但是我发现动态适合我的情况。



每个属性和方法都有效好的,像这些:

 保护覆盖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);
返回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的引用,它是一个未知的句柄。



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



提前感谢大家所有的支持,请原谅我我可怜的英语。

解决方案

将早期绑定到后期绑定调用使用COM对象的程序的通用策略是第一个写早期绑定。智能感知可以帮助您进入成功之路,确保您使用正确命名的方法,传递正确的参数,特别有助于您了解事件处理程序签名的外观。



哪个产生这个测试代码:

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


I think this article has the same problem with me. However, there's no workable solution for my case.

I'm using Windows Media Player ActiveX in my program.

For some reason, I don't want to add a reference of it and convert to AxHost automatically by IDE.

I create the instance by 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;
}

I was tried to do this by Reflection, but I found that dynamic is suitable to my case.

Every property and method works alright, like these:

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

Unfortunately, when I want to attach event like the article I indicated in the top, it got no work.

My code like this:

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

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

I've checked the type of event handler of StatusChange, it's EventHandler.

These codes compiled well, and I can load some music, play it, pause it, ...do anything I like.

But the StatusChange event never triggered.

I tried to set a break-point at connectEvent.

When run at _wmp.StatusChange += new EventHandler(...), the IntelliTrace give me some information.

Those information had written in Trad. Chinese, I think it means:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Could not apply operator "+=" to type System.Dynamic.DynamicObject and System.EventHandler

Even though there's an exception, but just like I said, compile was passed, everything still work -- except I could not listen event.

So, how can I attach event successfully in the dynamic object _wmp?

Any possible solution (like Reflection) is useful to me.

Also, in the case above, the handler type of StatusChange is EventHandler.

But if I want to handle PlayStateChange event, it is an "Unknown handle" if I don't add a reference of wmp.dll.

I hope the solution is suitable to this case, too.

Thanks everyone in advance for all of your support, and please forgive me for my poor English.

解决方案

The generic strategy to turn a program that uses a COM object from early bound to late bound calling is to first write it early bound. IntelliSense will help you fall in the pit of success, ensuring that you use correctly named methods, pass the right kind of arguments and particularly useful to help you find out what the event handler signatures should look like.

Which produces this bit of test code:

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

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

With the StatusChange event handler assignment and method body completely auto-generated by IntelliSense. Note the signature of the event handler, it is not an EventHandler. Just a method that returns void and takes no arguments, it matches the Action delegate type. Now you have a good shot at writing the late-bound version without the undiagnosable runtime exceptions:

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

这篇关于如何将事件附加到动态对象或COM对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆