gpt4 book ai didi

c# - 使 DynamicMethod 调用其他方法

转载 作者:太空宇宙 更新时间:2023-11-03 12:36:08 26 4
gpt4 key购买 nike

我希望能够通过传递依赖于客户端代码的事件名称和操作来订阅任何对象的任何事件。我有以下代码

public static class EventSubscriber
{
public static object Subscriber<TEventArgs>(
this object obj,
string eventName,
Action handler,
Func<TEventArgs, bool> canExecute)
{
var eventInfo = obj.GetType().
GetEvent(eventName);

if (eventInfo == null)
throw new ArgumentException("Event name provided does not exist", nameof(eventName));

var handlerArgs = eventInfo.EventHandlerType.
GetMethod("Invoke").
GetParameters()
.Select(p => p.ParameterType).ToArray();



var method = new DynamicMethod("method", typeof (void), handlerArgs);
var generator = method.GetILGenerator(256);
generator.EmitCall(OpCodes.Call, handler.Method, null);

eventInfo.
AddEventHandler(
obj,
method.CreateDelegate(eventInfo.EventHandlerType));
return obj;
}
}

上面代码的用法:

var Polygons = new ObservableCollection<Polygon>(myList);
Polygons.Subscriber<NotifyCollectionChangedEventArgs>
("CollectionChanged",
() => MessageBox.Show("hello"),
e => e.OldItems != null);

它会在事件触发时引发 InvalidProgramException。我知道这是一个棘手的问题,我可以简单地使用 += 进行订阅,但是有人能告诉我为什么我的代码崩溃了吗?我想 ILGenerator.Emit 有问题,有什么建议吗?

最佳答案

您忘记在 DynamicMethod 的末尾返回。

var method = new DynamicMethod("method", typeof (void), handlerArgs);
var generator = method.GetILGenerator(256);
generator.EmitCall(OpCodes.Call, handler.Method, null);
generator.Emit(OpCodes.Ret); //every method must have a return statement

编译器为 () => MessageBox.Show("hello") lambda 创建的类是私有(private)的。 [reference]

当您在 public 类中使用 public static 方法时,它会起作用。

var Polygons = new ObservableCollection<Polygon>(myList);
Polygons.Subscriber<NotifyCollectionChangedEventArgs>
("CollectionChanged",
() => MessageBox.Show("hello"), //must in a public class and a public static method
e => e.OldItems != null);

关于c# - 使 DynamicMethod 调用其他方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40953480/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com