2010-07-13 4 views
6

플러그인 (MEF)을 사용할 수있는 응용 프로그램이 있습니다. 플러그인은 서비스를 가져 오는 WPF UserControls입니다.for 루프에 대리자를 할당 할 때의 문제

사용자는 응용 프로그램의 기본 메뉴에서 원하는 플러그인을 선택할 수 있습니다. 하나의 항목에 대해 매우 잘 작동

foreach(IToolPlugin Plugin in ToolPlugins) 
{ 
    Plugin.Init(); 
    MenuItem PluginMenuItem = Plugin.MenuItem; //New MenuItem but with Header set. 
    PluginMenuItem.Click += new RoutedEventHandler(delegate(object o, RoutedEventArgs e) { DoSomething(Plugin.Control);}); 
    PluginsMenu.Items.add(PluginMenuItem); 
} 

:

는이 작업을 수행하려면, 나는 다음과 같은 루프를 사용합니다. 그러나 플러그인이 두 개 이상 있으면 모든 menuitem이 마지막 루프의 대리자를 실행합니다. 적어도 마지막 루프의 Plugin.Control을 사용하십시오.

어떻게 해결할 수 있습니까?
도움 주셔서 감사합니다.

+5

나는 많은 것을보고 사랑 이 질문의 변형. – ChaosPandion

+0

@Chaos -이 경우 반드시 투표해야합니다.) – ChrisF

답변

8

루프의 각 반복에서 클로저에서 반복 값을 사용하기 전에 반복 값의 값을 "캡처"해야합니다. 그렇지 않으면 각 대리자의 Plugin은 익명 함수가 만들어 질 때 보유한 값 대신 Plugin의 마지막 값을 가리 킵니다.

당신은 여기 에릭 Lippert의에서 깊이 설명에 자세한 내용을보실 수 있습니다 : 한마디로

Closing over the loop variable considered harmful - Fabulous Adventures in Coding

, 당신의 foreach 루프를 작성하는 올바른 방법은 다음과 같습니다

foreach(IToolPlugin Plugin in ToolPlugins) 
{ 
    Plugin.Init(); 
    MenuItem PluginMenuItem = Plugin.MenuItem; 

    IToolPlugin capturedPlugin = Plugin; 

    PluginMenuItem.Click += 
     new RoutedEventHandler(delegate(object o, RoutedEventArgs e) { 
      DoSomething(capturedPlugin.Control); 
     }); 

    PluginsMenu.Items.add(PluginMenuItem); 
} 
+0

문제에 대한 Eric의 블로그 게시물에 대한 필수 링크를 포함 할 예정입니까? (루프 변수를 닫으면 위험한 것으로 간주됩니다.) –

+0

@ 존 스키트 - 예 ... 링크를 가져 오는 중입니다. –

+0

우리는이 질문에 대한 로타가 있어야합니다 :) (검색하기가 어렵 기 때문에 중복으로 닫을 가치가 있다고 생각하지 않습니다.) –

관련 문제