For the sake of completeness, I want to share the final version of my helper functions which can be used to connect and disconnect to any kind of event on an object.
private static Delegate CreateDelegate(Type delegateType, Action<object[]> target)
{
var sourceParameters = delegateType.GetMethod("Invoke").GetParameters();
var parameters = sourceParameters.Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray();
var castParameters = parameters.Select(p => Expression.TypeAs(p, typeof(object))).ToArray();
var createArray = Expression.NewArrayInit(typeof(object), castParameters);
var invokeTarget = Expression.Invoke(Expression.Constant(target), createArray);
var lambdaExpression = Expression.Lambda(delegateType, invokeTarget, parameters);
return lambdaExpression.Compile();
}
private static Type delegateFactory = typeof(V8ScriptEngine).Assembly.GetType("Microsoft.ClearScript.DelegateFactory");
private static MethodInfo createDelegateX = delegateFactory.GetMethod("CreateDelegate", new[] { typeof(ScriptEngine), typeof(object), typeof(Type) });
public Delegate AddEventHandler(object obj, string eventName, object callback) {
var eventInfo = obj.GetType().GetEvent(eventName);
if (eventInfo != null)
{
// Create a delegate from the JavaScript callback function
Delegate scriptHandler = (Delegate)createDelegateX.Invoke(null, new object[] { engine, callback, eventInfo.EventHandlerType });
var handler = CreateDelegate(eventInfo.EventHandlerType, (object[] args) =>
{
Debug.WriteLine("Event triggered: " + eventInfo.Name);
new Thread(() =>
{
scriptHandler.DynamicInvoke(args);
}).Start();
});
try
{
eventInfo.AddEventHandler(obj, handler);
}
catch (Exception ex)
{
Debug.WriteLine("AddEventHandler could not add event handler:" + ex.Message);
return null;
}
return handler;
}
return null;
}
public bool RemoveEventHandler(object obj, string eventName, Delegate handler)
{
var eventInfo = obj.GetType().GetEvent(eventName);
if (eventInfo != null)
{
eventInfo.RemoveEventHandler(obj, handler);
return true;
}
return false;
}