У меня есть приложение, которое способно к плагинам (MEF). Плагины являются WPF UserControls тот импорт сервисы.
Пользователь может выбрать требуемый плагин из главного меню приложения.
Чтобы сделать это, я использую следующий цикл:
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);
}
Это работает очень прекрасное на единственный объект. Но как только у меня есть больше чем 1 плагин, все пункты меню выполняют делегата последнего цикла. Или по крайней мере с Плагином. Управление последнего цикла.
Как я могу зафиксировать это?
Спасибо за любую справку.
На каждой итерации цикла вы должны "перехватывать" значение итерируемого значения, прежде чем использовать его в закрытии. В противном случае Plugin в каждом делегате будет указывать на последнее значение Plugin вместо значения, которое он имел при создании анонимной функции.
Вы можете прочитать более подробное объяснение от Эрика Липперта здесь:
Закрытие переменной цикла считается вредным - 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);
}