Raising event via reflection using web forms with codebehind
I understand that there are a number of questions that involve raising an event through reflection, however I could not find an answer to the following [I suspect the answer is no]:
Given the "standard" event declaration, is there a way to raise the event by referencing a string literal.
For example, pseudocode:
Dim eventName As String = "TestEvent"
RaiseEvent eventName
Obviously this won't work.
I can get the type of event / multicast handler with
Me.GetType.GetEvent("TestEvent").GetAddMethod.GetParameters(0).Name
// "TestEventEventHandler
But I cannot find an instance of this page object to call .GetInvocationList
It is similar to this question: How can I get the actual EventHandler delegate instance from an event in VB.NET?
However, here I am specifically looking at creating an event from a string.
Edit:
In the vb.net/webforms environment, several things are different. As per my comment on the accepted answer, due to (I believe) the nature of the code based model, it is not possible to return the field corresponding to the event from Me.GetType()
, as at runtime Me
refers to class inheritance in the .aspx file and not in the class in the .aspx.vb file.
What this really means is that I have to use the Me.BaseType.GetType()
search field.
The second thing that is different, although unrelated to the final answer, is that while in C # you can directly reference the MulticastDelegate event handler, in vb.net you cannot - or at least do this should use an undocumented feature not supported by intellisense, according to: How can I get the actual EventHandler delegate instance from an event in VB.NET?
source to share
The problem I ran into was that iterating through the collection of fields Me.GetType()
did not return the "TestEvent" field. Once again I worked and realized that this is because the event is declared in the "code behind" class, for example: myPageName.aspx.vb, but at runtime this code is called from the inheriting class "design", for example myPageName. ASPX.
This blog post states that even with BindingFlags.FlattenHierarchy
, .GetType.GetField()
will not return private static fields from inherited classes. http://bobpowell.net/eventsubscribers.aspx
As a result, the solution was to use Me.GetType.BaseType.GetField("TestEvent")
and from there use the technique described by Tejas Sharma. This answer offers a vb.net example of this method: How to attach events of a source object to a deeply copied clone
source to share
You can call GetField
on your instance of the type and then move on to the call GetValue()
on the return one FieldInfo
. Here is an example (in C #, because I am not talking about vb.net)
class Foo
{
public event EventHandler Bar;
}
class Program
{
static void Main(string[] args)
{
var foo = new Foo();
foo.Bar += FooOnBar;
var ev = (MulticastDelegate)foo.GetType().GetField("Bar", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(foo);
if (ev != null)
{
foreach (var del in ev.GetInvocationList())
{
del.Method.Invoke(del.Target, new object[] {foo, new EventArgs()});
}
}
Console.ReadLine();
}
private static void FooOnBar(object sender, EventArgs eventArgs)
{
Console.WriteLine("Invoked!");
}
}
source to share