Я использую приложение, позволяющее вставлять фрагменты кода c # в базу данных и компилировать их в DLL, которая перезагружается во время выполнения приложения.Я расширяю приложение, чтобы на настраиваемых сочетаниях клавиш отображалось окно поиска.
Почти все работает нормально, событие регистрируется и запускается правильно с первого раза, окно поиска работает.
Моя проблема возникает из-за событий KeyHandler между перекомпиляциями DLL (которые могут быть инициированы либо мной, либо другим пользователем, вносящим изменения в базу данных).
Как я могунайти ранее зарегистрированный обработчик KeyDown и удалить его?
Общий процесс
- Загрузка приложения
- Вставка пользовательского фрагмента и компиляция в DLL с уникальным именем
- Изменение пользовательского фрагмента во время выполнения
- Приложение обнаруживает изменение и DLL перекомпилируется с новым именем
Имя файла DLL основано на контрольной сумме, поэтому оно будет измененодаже если комментарии добавлены, и у меня нет никакого контроля над этим.
Код для создания элемента управления и добавления обработчика KeyDown, вызываемого один раз для компиляции
public class InitApp {
public void InitKeyBinding() {
MainForm activeForm = AppManager.DialogParent;
var controls = activeForm.Controls.Find("SearchBox", false);
foreach (Control ctrl in controls) {
ctrl.Dispose();
}
AutoCompleteTextBox txt_Search = new AutoCompleteTextBox();
activeForm.KeyPreview = true;
activeForm.KeyDown -= AllegroSearchBox.OpenSearchBox;
activeForm.KeyDown += AllegroSearchBox.OpenSearchBox;
return void;
}
}
Код, который показывает поле на основеправильный ярлык, вызываемый при каждом событии KeyDown
public static class SearchBox {
public static void OpenSearchBox(object sender, KeyEventArgs e) {
MainForm activeForm = AppManager.DialogParent;
if (e.Control && e.Shift && e.KeyCode == Keys.N) {
var controls = activeForm.Controls.Find("SearchBox", false);
if (controls.Any()) {
((AutoCompleteTextBox)controls.First()).SetAllVisible();
}
e.Handled = true;
}
}
}
public class AutoCompleteTextBox : TextBox {
public AutoCompleteTextBox() {
MainForm activeForm = AppManager.DialogParent;
this.Name = "SearchBox";
this.Visible = false;
this.Width = 400;
activeForm.Controls.Add(this);
}
public void SetAllVisible() {
this.Visible = true;
}
}
Приведение элемента управления к AutoCompleteTextBox вызывает проблемы.
Поскольку и AutoCompleteTextBox, и класс SearchBox, которые были зарегистрированы при начальной загрузке приложения (версия DLL [A]), больше не существуют, отмена регистрации события не удалась.И второе событие теперь регистрируется в новой версии классов (версия DLL [B]).
Сообщение об ошибке
[A]AutoCompleteTextBox cannot be cast to [B]AutoCompleteTextBox.
Type A originates from 'b6s6ARS1_6wG6Gt_XkVoWeh5a1u8ea7JSZp9bfTQ78Q,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
in the context 'LoadFrom' at location
'C:\db06\Bin\b6s6ARS1_6wG6Gt_XkVoWeh5a1u8ea7JSZp9bfTQ78Q.dll'.
Type B originates from 'oYka1c8YhqEFWWFpX4TJFcd+f8sz15riYKSJVnKAkn0,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
in the context 'LoadFrom' at location
'C:\db06\Bin\oYka1c8YhqEFWWFpX4TJFcd+f8sz15riYKSJVnKAkn0.dll'.
Метод OpenSearchBox теперь вызывается 2 раза, первыйгенерирует указанное выше исключение, а второе работает нормально.При каждой дополнительной перекомпиляции он будет ломать текущий KeyHandler и добавлять новый.
Я смог скрыть проблему, добавив попытку catch вокруг явного приведения, но это неоптимальныйрешение!Кроме того, в качестве AutoCompleteTextBox используется controls.First (), который возвращает значение null, поскольку предыдущая версия класса больше не существует.
Я действительно хотел бы удалить старый обработчик, а не пытаться / ловить или проверять ноль вокруг него.
Большое спасибо за любые предложения, включая редизайн:)