Checking that an event has handlers added to it - using Reflection

J

jehugaleahsa

Hello:

I am creating a simple class library for simplifying reflection.

I am creating an EventWrapper class that allows programmers to treat
it like an event (minus the operator overloading).

I am concerned with how to check that handlers have been added to the
event prior to raising it.

For instance,

if (TextChanged != null)
{
TextChanged(this, EventArgs.Empty);
}

tests whether there are any handlers prior to raising the event. How
can I do this with the EventInfo class?

Thanks!
 
M

Marc Gravell

Basically there is no robust way of doing this... your cited code
masks a compiler trick - a hidden delegate field. EventInfo points to
the accessors, not the implementation.
It is (commonly) the *field* (sitting behind the accessors) that has
the value, and you'd need to check that. But sometimes the field is
developer-generated (with custom add/remove accessors) and sometimes
there *is* no such field (perhaps using EventHandlerList). Or perhaps
it does something even more esoteric - registers subscribers in a
centralised class for some reason.

Marc
 
J

jehugaleahsa

Basically there is no robust way of doing this... your cited code
masks a compiler trick - a hidden delegate field. EventInfo points to
the accessors, not the implementation.
It is (commonly) the *field* (sitting behind the accessors) that has
the value, and you'd need to check that. But sometimes the field is
developer-generated (with custom add/remove accessors) and sometimes
there *is* no such field (perhaps using EventHandlerList). Or perhaps
it does something even more esoteric - registers subscribers in a
centralised class for some reason.

Marc

It sounds like I should just let an error happen then. What would be
the benefit of masking it with a try {} catch {}. Would the hide
errors that took place in the event handlers? or would it just hide
that the event didn't have any listeners?
 
M

Marc Gravell

It sounds like I should just let an error happen then. What would be
the benefit of masking it with a try {} catch {}. Would the hide
errors that took place in the event handlers? or would it just hide
that the event didn't have any listeners?

To be honest, I'm confused as to how you are going to (robustly) do
*anything* useful (other than subscribe/unsubscribe) with an
EventInfo. If you are thinking of using the GetRaiseMethod(), then
note the remark on MSDN:
<q>This method returns a null reference (Nothing in Visual Basic) for
events declared with the C# event keyword or the Visual Basic Event
keyword. This is because the C# and Visual Basic compilers do not
generate such a method.</q>

http://msdn2.microsoft.com/en-us/library/1a4k4e35.aspx

Marc
 
J

jehugaleahsa

To be honest, I'm confused as to how you are going to (robustly) do
*anything* useful (other than subscribe/unsubscribe) with an
EventInfo. If you are thinking of using the GetRaiseMethod(), then
note the remark on MSDN:
<q>This method returns a null reference (Nothing in Visual Basic) for
events declared with the C# event keyword or the Visual Basic Event
keyword. This is because the C# and Visual Basic compilers do not
generate such a method.</q>

http://msdn2.microsoft.com/en-us/library/1a4k4e35.aspx

Marc

I will have to test this. Thank you for bringing that to my attention.

Ah . . . you are right. MSDN is right. How the heck will I be able to
raise events for dynamically generated code?
 
M

Marc Gravell

Maybe if you post how you expect to eventually consume the completed
EventWrapper (i.e. your use-case) we might suggest the best solution?
 
J

jehugaleahsa

Maybe if you post how you expect to eventually consume the completed
EventWrapper (i.e. your use-case) we might suggest the best solution?

Maybe if you post how you expect to eventually consume the completed
EventWrapper (i.e. your use-case) we might suggest the best solution?

Here is the gist of what I am trying to do.

We have lots of business objects to make for lots of projects. Right
now the most time-consuming thing is the creation of the business
objects, writing each of their properties, writing all their SQL and
all the other gobbledy gook.

I want to make a tool that allows the developer to pick columns from
tables (which I have already done) and have it pull out the correct
type, do string length/other data verification, and write base-line
SQL. I have everything I need to do that now. I wrote a reflection
class that can execute generated code. I have code that builds C# and
compiles it.

Now, generally, I don't intend to run the generated Assemblies, or
generate them. My main intent is to create the source code, which I
have already done. However, I am currently in the process of creating
an XML-based format that will allow me to configure B.O.s and have the
effects take place instantly without needing to recompile. The problem
comes when my . . . wait a minute!

Actually, now that I think about it, you can only raise an event
inside a class anyway! My source code generator should be responsible
for creating code for raising events, not the EventInfo class. The
only thing you really should be able to do to a reflected Event *is*
add or remove handlers, which my code already supports.

I can't think of a good reason to allow reflection to raise events.
Thank you for the verification. Now I can get this code generator to
work!

Thanks, you may have just helped me save my company a lot of time and
money.

!Travis
 
M

Marc Gravell

Here is the gist of what I am trying to do.

We have lots of business objects to make for lots of projects. Right
now the most time-consuming thing is the creation of the business
objects, writing each of their properties, writing all their SQL and
all the other gobbledy gook.

I want to make a tool that allows the developer to pick columns from
tables (which I have already done) and have it pull out the correct
type, do string length/other data verification, and write base-line
SQL. I have everything I need to do that now. I wrote a reflection
class that can execute generated code. I have code that builds C# and
compiles it.

Now, generally, I don't intend to run the generated Assemblies, or
generate them. My main intent is to create the source code, which I
have already done. However, I am currently in the process of creating
an XML-based format that will allow me to configure B.O.s and have the
effects take place instantly without needing to recompile. The problem
comes when my . . . wait a minute!

Actually, now that I think about it, you can only raise an event
inside a class anyway! My source code generator should be responsible
for creating code for raising events, not the EventInfo class. The
only thing you really should be able to do to a reflected Event *is*
add or remove handlers, which my code already supports.

I can't think of a good reason to allow reflection to raise events.
Thank you for the verification. Now I can get this code generator to
work!

Thanks

No problem, but on this occasion I'm genuinely not sure I did
anything! For reference the common pattern is:

public event SomeEventHandler SomeEvent; // optionally bespoke add/
remove

protected void OnSomeEvent(...) { // args perhaps by delegate
signature
// code that fires SomeEvent
}

then you can simply find you EventInfo and then look for a MethodInfo
based on On{TheName}

Marc
 

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