Хорошо, я размышлял над этой идеей весь день, и я дошел до того, что признаю, что просто потонул, не знаю. Возможно, то, что я делаю, просто глупо и есть лучший способ, но это то, куда меня привело мое мышление.
Я пытаюсь использовать универсальный метод для загрузки форм в WinForms:
protected void LoadForm<T>(ref T formToShow, bool autoLoaded) where T : FormWithWorker, new()
{
// Do some stuff
}
Формы загружаются с помощью ToolStripMenuItem (либо путем выбора элемента, либо с помощью пункта меню «Открыть Windows»). Они загружаются лениво, поэтому в формах родителя MDI есть поля для форм, но они пусты до тех пор, пока они не понадобятся. У меня есть общий метод, используемый для ToolStripMenuItem_Click, который обрабатывает все щелчки по пунктам меню. У метода нет реального способа узнать, для какой формы вызывается, за исключением того, что имя ToolStripMenuItem соответствует шаблону, выбранному для имен классов форм, которым они соответствуют. Таким образом, используя имя ToolStripMenuItem, я могу определить название типа запрашиваемой формы и имя частного поля, выделенного для хранения ссылки на эту форму.
Используя это, я могу либо использовать растущий / сжимающийся оператор switch с жестко закодированными типами и совпадениями строк для вызова метода с определенным набором типов (нежелательно), либо я могу использовать Reflection, чтобы получить поле и создать экземпляр тип. Для меня проблема в том, что System.Activator.CreateInstance
предоставляет ObjectHandler, который не может быть приведен к нужным мне типам. Вот фрагмент того, что у меня есть:
string formName = "_form" + ((ToolStripMenuItem)sender).Name.Replace("ToolStripMenuItem", "");
string formType = formName.Substring(1);
FieldInfo fi = this.GetType().GetField(formName, BindingFlags.NonPublic | BindingFlags.Instance);
FormWithWorker formToLoad = (FormWithWorker)fi.GetValue(this);
if (formToLoad == null)
{
formToLoad = (????)System.Activator.CreateInstance("MyAssemblyName", formType);
}
this.LoadForm(ref formToLoad, false);
fi.SetValue(this, formToLoad);
Я знаю строковое имя типа, который используется для (????), но во время компиляции я не знаю тип, потому что он изменяется. Я попробовал несколько способов заставить этот каст / инстанцирование работать, но ни один не был успешным. Мне бы очень хотелось узнать, возможно ли выполнить такое приведение, зная тип только как строку. Я пытался использовать Type.GetType(string, string)
для выполнения приведения, но компилятору это не понравилось. Если у кого-то другое представление о том, как загружать формы динамически, потому что я просто делаю это глупо, пожалуйста, дайте мне знать об этом.