views:

63

answers:

1

I've been trying figure out how to add a handler to a method using Codedom, but am not getting very far.

The method I want to reproduce via Codedom is:

Private Sub Startup() Handles btnStart.Click
    ''# Do work
End Sub

The method is easy enough to create with:

Dim StartupMethod As New CodeMemberMethod
StartupMethod.Name = "Startup"
StartupMethod.Attributes = MemberAttributes.Private

But I can't figure out how to add the Handles btnStart.Click. I've looked at CodeAttachEventStatement, but this I don't believe it can do a Handles on a method.

Does anyone know how to achieve this?

EDIT: The solution below works for VB, but does not work for C# because the handler is looking to handle an event rather than a method.

+3  A: 

Handles is just a syntactic sugar vb.net offers you for your convenience. Under the hood it is converted to:

AddHandler btnStart.Click, AddressOf Startup

So I think it won't be possible. You should try to use the CodeAttachEvent statement instead

http://msdn.microsoft.com/en-us/library/system.codedom.codeattacheventstatement.aspx

Another possibility is to use CodeSnippetTypeMember() as described here

http://stackoverflow.com/questions/1820425/workaround-for-vb-net-partial-method-using-codedom/1836564#1836564

SchlaWiener
so you're saying I should use the above to initialize the handler, like in constructor `New()` statement?
Otaku
+1, yes, generate the constructor and use CodeAttachEventStatement.
Hans Passant
Yes, I haven't done it yet, but I bet you would find AddHandler methods in the New() constructor if you inspect your `Handles ...` code in reflector.
SchlaWiener
Got that, it's working, unfortunately it now produces a problem when using a CSharp provider. It produces code like `btnStart.Click += new System.EventHandler(this.Startup);` when it should just produce `btnStart.Click += this.Startup;` - I think the error is related to the fact that the method isn't declared an event.
Otaku
In C# it's supposed to be btnStart.CLick += new System.EventHandler(this.Startup) so I dont think that's the cause of your error Otaku
PsychoCoder
@PsychoCoder: For this: `private void Startup(){}`?
Otaku
Found this interesting article about how the VB.Net `Handles` keyword is translated internally http://codebetter.com/blogs/peter.van.ooijen/archive/2005/08/02/130194.aspxIt also removes an existing handler if necesarry.
SchlaWiener
@Otaku, the signature of your Startup Method should be `Private Sub Startup(ByVal sender as Object, ByVal e as System.EventArgs)`.VB.Net allows you to add handlers to a method with an empty signature since VS 2008. But I suppose that is syntactic sugar, too and internally a method with the correct signature is added that only calls the `Startup()` method. You can't do that in C#
SchlaWiener
@SchlaWiener: I left out the arguments in the method just for simplicity and less code. I'm looking at the link you posted above, it's really interesting. I'm still trying to wrap my head around how C# does things and why it's not explicit. Mostly, I'm just trying to get Codedom to do the same thing in both languages. More soon after I've researched this some more.
Otaku
@Otaku - I always use the right signature from start. It makes it more readable since the `sender, e` signature already shows in which context this method is used without further comments. If you need the `sender` or `e` later, you have to refactor your code anyway. And since you want your code to be compatible with c# and vb.net you wont have a choise.
SchlaWiener
@SchlaWiener: Thanks much for your help here.
Otaku