Joe*_*ton 7 c# reflection casting winforms
好吧,我现在整天都在喋喋不休地谈论这个想法,而且我已经达到了我承认我不知道的地方.我正在做的事情可能只是愚蠢而且有更好的方法,但这是我思考带给我的地方.
我试图使用通用方法在WinForms中加载表单:
protected void LoadForm<T>(ref T formToShow, bool autoLoaded) where T : FormWithWorker, new()
{
// Do some stuff
}
Run Code Online (Sandbox Code Playgroud)
表单由ToolStripMenuItem加载(通过选择项目或使用Open 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);
Run Code Online (Sandbox Code Playgroud)
我知道(????)类型的字符串名称,但在编译时我不知道类型,因为它改变了.我已经尝试了一些方法来使这个演员/实例化工作,但没有一个成功.我非常想知道是否可以执行这样的演员表示只知道字符串类型.我尝试使用Type.GetType(string, string)
执行转换,但编译器不喜欢它.如果有人对如何动态加载表单有不同的想法,因为我只是愚蠢地做,请告诉我.
Meh*_*ari 13
此问题通常通过强制转换为所有可能类型的公共基类或接口来解决.
在C#4中,您还可以将其分配给dynamic
变量以保存返回值并在其上调用任意方法.这些方法将被延迟绑定.但是,我倾向于尽可能坚持以前的解决方案.
对于需要和使用例如的其他重载,你会更好.Type
Type.GetType(string)
FormWithWorker formToLoad = (FormWithWorker)fi.GetValue(this);
if (formToLoad == null)
{
formToLoad =
(FormWithWorker)System.Activator.CreateInstance(Type.GetType("MyNamespace.MyFormType"));
}
Run Code Online (Sandbox Code Playgroud)