2011-03-11 112 views
3

我正在使用AssemblyResolve。这是我的代码第一,然后我的问题如下:将自己的参数发送给事件处理程序?

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

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

因此,我将HandleIt添加到我的AssemblyResolve事件。我怎样才能把它添加到该事件,并传递一个参数,它像:

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

这是扔我了,因为HandleIt接受参数,但是当它被添加到AssemblyResolve事件没有被explicetly通过。我希望是这样的:

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

所以,是的,我只是希望能够将它添加到我的AssemblyResolve事件时,另外一个参数发送给我的HandleIt功能。

希望有道理,谢谢。

附录:

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){ 

} 

航班吗

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){ 

} 
+0

你不需要的,如果(aBool)在lambda版本,你可以简单地say'a.AssemblyResolve + =(对象S,ResolveEventArgs一)= >拉手(S,A,aBool);'或曾经的说法应该是什么 – 2011-06-26 14:01:17

回答

7

当事件被触发参数传递给方法,如果你要绑定额外的参数,你可以这样做与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 
} 

其中someArgument是你希望绑定值。

这实质上是使用lambdas来完成函数的部分应用。 C#不直接支持的东西,但在其他语言中很常见。部分应用程序与当前存在于诸如F#和Haskell之类的语言中的Currying关系非常密切(因为该概念从Haskell Curry获得它的名称)以及各种其他函数式语言。它们在结果类型上有所不同。

它们都涉及到关闭(如上面的代码的概念被称为),并在不支持部分应用程序或讨好你可以使用闭包来完成类似的语言。但请注意,关闭与部分应用程序的不同之处在于会产生一些令人惊讶的错误。例如。

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

System.Console.WriteLine(f()); 

2打印到控制台。因为封闭件捕获参考给一个变量不是所述变量的值。当关闭for循环的循环变量时,这是for循环中的常见错误。

+0

这是非常聪明的,谢谢你的提示。 – asawyer 2011-03-11 21:34:35

+0

投了票,而不是我的回答 – DaveShaw 2011-03-11 21:35:07

+0

这在手动触发事件实现自己的目标没有帮助。查看我答案中的更新。 – 2011-03-11 21:37:47

2

AppDomain.CurrentDomain将引发事件和传递参数,所述+ =行简单地注册一个处理程序来的情况下,参数将有没有任何意义。

打个比方:

您注册邮递员您的地址,他deilivers向该地址发送邮件后。当您在邮局注册时,您不会向他们发送您希望稍后交付给您的邮件!

+0

当然,我可以看到我的理解是更糟糕的,我认为它是前。也许它甚至没有意义,我想要做什么,这是:我故意触发AssemblyResolve选择我自己的DLL在运行时加载。我想能够说:通过传递一个参数到我的AssemblyResolve事件处理程序来加载这个或那个DLL。这会改变什么吗? – sooprise 2011-03-11 21:33:29

+0

看看符文FS的回答。另外,如果这是你想要做的,这应该是你的问题! – asawyer 2011-03-11 21:35:54

0

技术性更强一点:您正在为事件注册一个委托给您的方法。这不是对方法的调用。 这是一个有点类似于此:

Action<object, ResolveEventArgs> handleItDelegate = HandleIt; 

当事件被激活时,委托被调用。我的样品的比喻是:

handleItDelegate(sender, eventArgs); 

UPDATE:
在一个评论,你澄清,你想达到什么样的:你要触发事件,那么您的组件加载。你不能这样做,你认为它的工作方式。要手动加载组件,只需这样做,不需要事件。当运行时试图解析引用的程序集,但找不到它时,调用该事件。

1

这是不可能的。 HandleIt在这种情况下是一个委托,具有匹配ResolveEventHandler

a.AssemblyResolve += new ResolveEventHandler(HandleIt); 

的签名在此行中设置它只是告诉代码时AssemblyResolve上升引发此AssemblyResolved活动将通过它的东西要执行什么参数。你可以用你自己的参数重新引发另一个事件,并将其挂钩到另一个处理程序(或者只是调用一个方法)。

编辑:或者,也许你可以用的Lamda的:○

+0

这是否是“最佳实践”方法?我可以看到我可以通过lambda表达式混乱地添加参数。 – sooprise 2011-03-11 21:35:32

+0

可能不是。我赞成Lamda的回答。 – DaveShaw 2011-03-11 21:36:42

+0

这就是我过去为这类问题所做的。那lambda的东西虽然很漂亮。 – asawyer 2011-03-11 21:37:43

相关问题