GetFileld fails - ReflectionPermission problem?

D

dan

Hi all,
I have a reflection-problem I'm totally stuck with. Maybe someone has a
hint...
I want to get a fieldinformation of an event from the Control class, e.g.
"TextChanged".

FieldInfo fi = typeof(Control).GetField("TextChanged",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Public);

This should return the FieldInfo of the Control.TextChanged-event.But it
doesn't! It returns null.
If I do the same code on my self defined class, it works perfectly. The only
thing I can guess, is that
I should grant permission with ReflectionPermission. I have the default
settings for security and the
security tool tells me there is no security on the windows.forms-assembly.

Anybody can help me?
Thanks in advance

Dan

Full code below:
-------------------------

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;

namespace ReflectionTest
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Tester
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
//MyClass
EventInfo ei1 = typeof(MyClass).GetEvent("MyEvent");
FieldInfo fi1 = typeof(MyClass).GetField("MyEvent",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Public);

//Control
EventInfo ei2 = typeof(Control).GetEvent("TextChanged");
FieldInfo fi2 = typeof(Control).GetField("TextChanged",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Public);

//why is fi2 == null ?????
}

class MyClass
{
public event EventHandler MyEvent;
}
}
}
 
J

Jon Skeet [C# MVP]

dan said:
I have a reflection-problem I'm totally stuck with. Maybe someone has a
hint...
I want to get a fieldinformation of an event from the Control class, e.g.
"TextChanged".

FieldInfo fi = typeof(Control).GetField("TextChanged",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Public);

This should return the FieldInfo of the Control.TextChanged-event.But it
doesn't! It returns null.

Events aren't necessarily stored as fields. In Control, for instance, I
believe that all the events are stored in the component's
EventHandlerList.

Think of it as being similar to properties - just because there's a
property named Foo doesn't mean there's necessarily a field backing it
called foo.

Indeed, it's not even necessary that your code will work on your own
class. The C# compiler is free to use whatever field name it wants. For
instance, the language specification has this example:

<quote>
Thus, an instance event declaration of the form:

class X {
public event D Ev;
}

could be compiled to something equivalent to:

class X {
private D __Ev; // field to hold the delegate
public event D Ev {
add {
lock(this) { __Ev = __Ev + value; }
}
remove {
lock(this) { __Ev = __Ev - value; }
}
}
}

Within the class X, references to Ev are compiled to reference the
hidden field __Ev instead. The name "__Ev" is arbitrary; the hidden
field could have any name or no name at all.
</quote>

It so happens that the MS C# compiler picks the same name for the field
as for the event, but that's not in the specification - and that's only
field-like events, let alone events which don't use a "field per
event" model at all.
 
J

Jon Skeet [C# MVP]

dan said:
I have a reflection-problem I'm totally stuck with. Maybe someone has a
hint...

<snip>

In my previous post I told you why it didn't work. I neglected to give
you an alternative :)

I suggest you get the event itself using Type.GetEvent instead. You can
then add/remove handlers from it.
 
D

dan

Hi Jon,
thanks a lot for this very fast and precise answer! You're completly right.
I checked it out with Anakrino.
That's the code it decompiles.

public void add_KeyPress(KeyPressEventHandler value)
{
this.Events.AddHandler(Control.EventKeyPress, value);
}

So Control adds its events effectively to the Events property of the
Component class.
I spent a few hours the find a solution. But I'm really happy to know why it
didn't work :)

The purpose behind my question actually was to figure out, which handler are
attached at the event.
In a class, where the event is defined as a "real" event, I could do so by
writing the following code:

object val= fieldinfo.GetValue(anObject);
MulticastDelegate md = (MulticastDelegate)val;
Delegate[] list = md.GetInvocationList();

This would have been a general way to figure out which events are attached
to an event.
Obviously, this doesn't work on Control. Instead I could get the events
field, which is an EventHandlerList
and ask it for the contained handlers.

Anyway, it was a pleasure to get incredible fast such a competent answer!

Daniel Frey
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top