Recibo todos los eventos, con cierto atributo, y deseo modificar estos eventos agregando una llamada a otro método.¿Cómo puedo cambiar un método asignado en un evento?
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
**/
}
}
Lo que quiero es básicamente lo que se comentó anteriormente. "Modificar" los métodos suscritos del evento. Supongo que no me puedo suscribir porque necesito pasar los parámetros que el método está pasando al controlador grande (el nuevo método).
Un ejemplo más basado en on this question. Quiero convertir esto:
var e += (x) =>
{
var y = x;
};
Para algo como esto:
var e += (x) =>
{
var y = x;
BigHandler(x); // injected code
};
O esto:
var e += (x) => // new method
{
previousE(x); // previous method
BigHandler(x); // additional code
}
¿Cómo puedo hacerlo?
El objetivo más grande:
que necesito para "detectar" cuando se dispara un evento y llamar a un método. También necesito enviar los parámetros que está usando.
que yo pueda hacer algo como:
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);
}
Entonces en mi método de control que se puede comprobar si se ha disparado un evento de XYZ
, comprobar qué evento fue despedido, recuperar el parámetro y hacer algo. Por ejemplo:
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);
}
}
Sé que se puede lograr utilizando PostSharp
, pero no puedo usarlo. Necesito otra solución.
relacionados
- C# Reflection, changing a method's body
- How can I dynamically inject code into event handlers in Delphi?
actualización 2010-09-27 no pude encontrar una solución ni más información sobre es, todavía necesito ayuda. Se agregó +150 recompensa.
Agregué el "objetivo más grande". Tu respuesta actual está cerca, siento haber olvidado mencionar que necesito obtener los parámetros que está pasando el método de suscripción. He agregado más información ... – BrunoLM
@ BrunoLM: Eso es solo cuestión de crear el delegado apropiado, por su aspecto. Voy a salir ahora, pero echaré un vistazo en aproximadamente una hora, si aún no lo has resuelto. Las expresiones Lambda bien pueden ser tu amigo. –
@Jon Skeet: Todavía no lo entiendo ... ¿Cómo puedo obtener el objeto que está usando el evento? La única forma en que puedo pensar es modificar el mismo método. Necesito algo como 'BigHandler (eventName, params_from_the_event.ToArray