从methodinfo创建委托(2)

编程入门 行业动态 更新时间:2024-10-26 04:31:37
本文介绍了从methodinfo创建委托(2)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我的情况是我想要一个来自Control的方法的委托。 为此,我使用如下代码:

My Situation is that I want to have a Delegate to a method from a Control. For that I use the code as follows :

Private RepeatDelayCounter As Integer = 0 Private RepeatControl As Control = Nothing Private Delegate Sub delegate_OnClick(instance As Control, e As System.EventArgs) Private RepeatDelegate As delegate_OnClick = Nothing Private Sub Button_Down(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) RepeatControl = sender RepeatDelegate = Nothing Dim myType As Type = RepeatControl.GetType Dim myInfo As System.Reflection.MethodInfo = myType.GetMethod("OnClick", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance) If myInfo IsNot Nothing Then RepeatDelegate = [Delegate].CreateDelegate(GetType(delegate_OnClick), myInfo, False) RepeatDelayCounter = 0 End Sub

你应该知道这只是一部分复杂类的(但相关的)。 如果启动Button_Down方法的Control使用覆盖版本,则此代码正常工作(我得到一个委托) OnClick方法。 如果我不使用自定义控件但使用标准控件(例如按钮),我会得到正确的MethodInfo,因为这个Control里面有一个OnClick-Method,但是我找不到一个委托。 错误消息我得到指向Binding-Flags,但是这些与我的那些完全相同自定义控件。所以我认为它来自标准-Control的OnClick方法的Protected属性。 所以...我需要的是一个有用的建议如何解决这个问题 - 因为我想了解它... ;-) 我尝试过的事情: 见上文...

You should know that this is only a part (but the relevant one) of a complex class. This code works properly (I get a Delegate) if the Control which starts the Button_Down-method uses a overrided Version of the OnClick-method. If I don't use a customized Control but a "Standard"-Control (for example a Button) I get the right MethodInfo, because this Control has a OnClick-Method inside, but I can't get a Delegate. The Error-Message I get points to the Binding-Flags, but these are completely the same as those from my custom Control. So I think it comes from the Protected-attribute of the OnClick-method from the "Standard"-Control. So ... what I need is a useful advice how to solve this - because I want to understand it ... ;-) What I have tried: see above ...

推荐答案

根据一些原油测试,我怀疑问题实际上是另一种方式:当没有被覆盖时,你可以创建委托,而你不能创建委托当方法已被重写时。 Based on some crude testing, I suspect the problem is actually the other way round: you can create the delegate when the method hasn't been overridden, and you can't create the delegate when the method has been overridden. Class Foo Protected Overridable Sub Click() Console.WriteLine("Foo.Click") End Sub End Class Class Bar : Inherits Foo End Class Class Baz : Inherits Foo Protected Overrides Sub Click() Console.WriteLine("Baz.Click") MyBase.Click() End Sub End Class Delegate Sub MyDelegate(ByVal instance As Foo) Function CreateDelegate(ByVal instance As Foo) As MyDelegate Dim myType As Type = instance.GetType() Dim myInfo As MethodInfo = myType.GetMethod("Click", BindingFlags.NonPublic Or BindingFlags.Instance) Return DirectCast([Delegate].CreateDelegate(GetType(MyDelegate), myInfo, True), MyDelegate) End Function Sub Main Dim f As New Foo() CreateDelegate(f).Invoke(f) ' OK: Prints "Foo.Click" f = New Bar() CreateDelegate(f).Invoke(f) ' OK: Prints "Foo.Click" f = New Baz() CreateDelegate(f).Invoke(f) ' ArgumentException: ' Cannot bind to the target method because its signature or security ' transparency is not compatible with that of the delegate type. End Sub

原因很简单。重写该方法后, GetMethod 将返回 MethodInfo ,表示该方法的重写版本。只能在声明覆盖的类的实例上调用该重写版本。但是你试图将它绑定到一个可以在基类的任何实例上调用的委托。 所以,例如,您可以创建一个委托来调用 Baz.Click ,但是传入一个 Bar 的实例。 简单的解决方案是检索基本方法的 MethodInfo :

The reason is fairly simple. When the method has been overridden, the GetMethod returns a MethodInfo representing the overridden version of the method. That overridden version can only be called on an instance of the class where the override is declared. But you are trying to bind it to a delegate that can be called on any instance of the base class. So, for example, you could create a delegate to call Baz.Click, but pass in an instance of Bar instead. The simple solution is to retrieve the MethodInfo for the base method:

Function CreateDelegate(ByVal instance As Foo) As MyDelegate Dim myType As Type = GetType(Foo) Dim myInfo As MethodInfo = myType.GetMethod("Click", BindingFlags.NonPublic Or BindingFlags.Instance) Return DirectCast([Delegate].CreateDelegate(GetType(MyDelegate), myInfo, True), MyDelegate) End Function

调用delegate仍会调用被覆盖的版本:

Invoking the delegate will still call the overridden version:

f = New Baz() CreateDelegate(f).Invoke(f) ' OK: Prints "Baz.Click", then "Foo.Click"

所以你的代码会变成:

So your code would become:

Private Sub Button_Down(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) RepeatControl = sender RepeatDelegate = Nothing Dim myType As Type = GetType(Control) Dim myInfo As System.Reflection.MethodInfo = myType.GetMethod("OnClick", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance) If myInfo IsNot Nothing Then RepeatDelegate = [Delegate].CreateDelegate(GetType(delegate_OnClick), myInfo, False) RepeatDelayCounter = 0 End Sub

或者,你可以创建一个封闭的实例委托,你根本不需要 RepeatControl 成员:

Alternatively, you could create a closed instance delegate, and you wouldn't need the RepeatControl member at all:

Private RepeatDelayCounter As Integer = 0 Private Delegate Sub delegate_OnClick(ByVal e As System.EventArgs) Private RepeatDelegate As delegate_OnClick = Nothing Private Sub Button_Down(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) RepeatDelegate = Nothing Dim myType As Type = GetType(Control) Dim myInfo As System.Reflection.MethodInfo = myType.GetMethod("OnClick", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance) If myInfo IsNot Nothing Then RepeatDelegate = [Delegate].CreateDelegate(GetType(delegate_OnClick), sender, myInfo, False) RepeatDelayCounter = 0 End Sub

更多推荐

从methodinfo创建委托(2)

本文发布于:2023-11-05 04:15:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1559872.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:methodinfo

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!