[英]How can I change a method assigned on an event?
我正在獲取具有某個屬性的所有事件,並且我想修改這些事件,添加對另一個方法的調用。
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
**/
}
}
我想要的基本上是上面評論的內容。 “修改”事件的訂閱方法。 我想我不能訂閱它,因為我需要傳遞方法傳遞給大處理程序的參數(新方法)。
基於這個問題的另一個例子。 我想轉換這個:
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賞金。
如果你只是添加一個電話,那很簡單 - 你不需要獲取所有訂閱的代表或類似的東西; 只需訂閱反射:
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());
}
}
注意我們如何構造所需的確切類型的委托 - 但我們知道我們可以通過兼容的方法來做到這一點,只要一切都遵循正常的事件模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.