Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending My Own Arguments To A Event Handler?

I'm working with AssemblyResolve specifically. Here is my code first, then my question follows:

var a = AppDomain.CurrentDomain;
a.AssemblyResolve += new ResolveEventHandler(HandleIt);

Private Assembly HandleIt(object sender, ResolveEventArgs args){
    //Does stuff, returns an assembly
}

So I add HandleIt to my AssemblyResolve event. How can I add it to that event and pass an argument with it like:

a.AssemblyResolve += new ResolveEventHandler(HandleIt(AnArgument));

This is throwing me off since HandleIt takes arguments, but none are explicetly passed when it is added to the AssemblyResolve event. I would expect something like:

a.AssemblyResolve += new ResolveEventHandler(HandleIt(aSender,someArgs));

So yeah, I just want to be able to send another argument to my HandleIt function when adding it to my AssemblyResolve event.

Hope that makes sense, thanks.

Addendum:

if(aBool){
    a.AssemblyResolve += new ResolveEventHandler(HandleA);
}
else{
    a.AssemblyResolve += new ResolveEventHandler(HandleB);
}

HandleA(object sender, ResolveEventArgs args){
    Handle(true);
}
HandleB(object sender, ResolveEventArgs args){
    Handle(false);
}
Handle(bool isA){

}

-vs-

if(aBool){
    a.AssemblyResolve += (object s, ResolveEventArgs a) => Handle(s,a,true);
}
else{
    a.AssemblyResolve += (object s, ResolveEventArgs a) => Handle(s,a,false);
}

Handle(object sender, ResolveEventArgs args, bool isA){

}
like image 456
sooprise Avatar asked Mar 11 '11 21:03

sooprise


3 Answers

When the event is fired arguments are passed to the method if you would like to bind additional arguments you could do that with a lambdaexpression

var a = AppDomain.CurrentDomain;
a.AssemblyResolve += (object s,ResolveEventArgs a) => HandleIt(s,a,someArgument);

Private Assembly HandleIt(object sender, ResolveEventArgs args, SomeType arg){
    //Does stuff, returns an assembly
}

where someArgument is the value you wish to bind.

This is essentially using lambdas to do a partial application of a function. Something that C# doesn't support directly but is very common in other languages. Partial application is very closely related to Currying that exists in languages such as F# and Haskell of course (since the concept gets it's name from Haskell Curry) and various other functional langauages. They differ in the result type.

They are both related to closures (as the concept in the above code is called) and in languages that don't support partial application or currying you can use closures to accomplish something similar. However be aware that closures differ from partial application in ways that can create some surprising bugs. E.g.

int i = 1;
Func<int> f = () => i;
i = 2;

System.Console.WriteLine(f());

prints 2 to the console. Because closures captures a reference to a variable not the value of said variable. This is a common error in for loops, when closing over the loop variable(s) of the for loop.

like image 180
Rune FS Avatar answered Oct 14 '22 19:10

Rune FS


AppDomain.CurrentDomain will raise the event and pass parameters, the += line is simply registering a handler to the event, parameters there would not make any sense.

Analogy:

You register your address with the postman, and he deilivers mail to that address later. When you register at the post office, you do not hand them the mail you want delivered to you later!

like image 22
asawyer Avatar answered Oct 14 '22 20:10

asawyer


It's not possible. HandleIt in this case is a delegate to and has to match the signature of ResolveEventHandler

a.AssemblyResolve += new ResolveEventHandler(HandleIt);

Setting it in this line just tells the code what to execute when AssemblyResolve is raised the thing that raises the AssemblyResolved event will pass it's parameters. You could re-raise another event with your own parameters and hook that to another handler (or just call a method).

EDIT: Or maybe you can with Lamda's :o

like image 20
DaveShaw Avatar answered Oct 14 '22 21:10

DaveShaw