我正在获取具有特定属性的所有事件,并且我想修改这些事件,并添加对另一个方法的调用。
var type = GetType();
var events = type.GetEvents().Where(e => e.GetCustomAttributes(typeof(ExecuteAttribute), false).Length > 0);
foreach (var e in events)
{
var fi = type.GetField(e.Name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);
var d = (Delegate)fi.GetValue(this);
var methods = d.GetInvocationList();
foreach (var m in methods)
{
var args = e.EventHandlerType.GetMethod("Invoke").GetParameters().Select(p => Expression.Parameter(p.ParameterType, "p")).ToArray();
var body = m.Method.GetMethodBody();
/**
TODO:
Create a new method with the body of the previous
and add a call to another method
Remove current method
Add the new created method
**/
}
}
我想要的基本上是上面评论的内容。 “修改”事件的订阅方法。我想我不能订阅它,因为我需要传递方法传递给大处理程序的参数(新方法)。
另一个基于on this question的示例。我想转换一下:
var e += (x) =>
{
var y = x;
};
对于这样的事情:
var e += (x) =>
{
var y = x;
BigHandler(x); // injected code
};
或者这个:
var e += (x) => // new method
{
previousE(x); // previous method
BigHandler(x); // additional code
}
我该怎么做?
更大的目标:
我需要在事件被触发时“检测”并调用方法。我还需要发送它正在使用的参数。
所以我可以做类似的事情:
public delegate void OnPostSaved(Post p);
[Execute]
public event OnPostSaved PostSaved;
public void Save()
{
/* save stuff */
// assume that there is already an event subscribed
PostSaved(post);
}
然后在我的处理程序方法中,我可以检查来自XYZ
的事件是否被触发,检查触发了哪个事件,检索参数并执行某些操作。例如:
public void BigHandler(string eventName, params object[] p)
{
if (eventName == "PostSaved")
{
var post = p[0] as Post;
MessageBoard.Save("User posted on the blog: " + post.Content);
}
}
我知道可以使用PostSharp
来实现,但我无法使用它。我需要另一种解决方案。
相关
更新2010-09-27 我找不到解决方案既没有更多信息,我仍然需要帮助。增加了+150赏金。
答案 0 :(得分:4)
如果你只是添加一个电话,那真的很容易 - 你不需要获取所有订阅的代表或类似的东西;只需订阅反射:
var type = GetType();
// Note the small change here to make the filter slightly simpler
var events = type.GetEvents()
.Where(e => e.IsDefined(typeof(ExecuteAttribute), false));
foreach (var e in events)
{
// "handler" is the event handler you want to add
e.AddEventHandler(this, handler);
}
现在,我已经假设你想要做什么 - 即每次引发事件时调用你的方法一次。这与每次调用事件处理程序时调用方法不同,这是原始代码所做的。那是很多更难......但你真的需要吗?
(如果你能在这里提供更多关于更大目标的信息,那真的会有所帮助。)
请注意,我在这里提供的代码应该无论如何实现事件 - 它不依赖于它是一个类似字段的事件。
编辑:好的,这是一个完整的示例,展示了如何向任何与正常事件模式匹配的事件添加普通EventHandler
委托:
using System;
using System.Reflection;
class CustomEventArgs : EventArgs {}
delegate void CustomEventHandler(object sender, CustomEventArgs e);
class Publisher
{
public event EventHandler PlainEvent;
public event EventHandler<CustomEventArgs> GenericEvent;
public event CustomEventHandler CustomEvent;
public void RaiseEvents()
{
PlainEvent(this, new EventArgs());
GenericEvent(this, new CustomEventArgs());
CustomEvent(this, new CustomEventArgs());
}
}
class Test
{
static void Main()
{
Publisher p = new Publisher();
Type type = typeof(Publisher);
foreach (EventInfo eventInfo in type.GetEvents())
{
string name = eventInfo.Name;
EventHandler handler = (s, args) => ReportEvent(name, s, args);
// Make a delegate of exactly the right type
Delegate realHandler = Delegate.CreateDelegate(
eventInfo.EventHandlerType, handler.Target, handler.Method);
eventInfo.AddEventHandler(p, realHandler);
}
p.RaiseEvents();
}
static void ReportEvent(string name, object sender, EventArgs args)
{
Console.WriteLine("Event {0} name raised with args type {1}",
name, args.GetType());
}
}
请注意我们必须构建所需的确切委托类型 - 但我们知道我们可以通过兼容的方法完成此操作,只要一切都遵循正常的事件模式。