我有一个名为Router的公共静态类,其中包含一些类似的表单引用;
public static class Router
{
static frmLogin rLogin = new frmLogin();
static frmDashboard rDashboard = new frmDashboard();
static frmReport rReport new frmReport();
}
我正在尝试创建一个名为"Route"的函数——这个函数将使用一个字符串参数,该参数将至少匹配其中一个表单引用。匹配时,所选表单将调用其"Index()"方法。(每个表单都预先构建了一个Index(),我只需要它被称为)
除了我创建一个类似MVC的结构是出于一个非常具体的原因之外,没有太多关于这个目的的话要说。因此,任何其他建议都将不胜感激。
总之,我需要通过名称找到正确的Form引用,即"rLogin",使用传递到"Route"方法的参数,该方法最终将调用该表单上的"Index()"函数。
我知道这可能与Reflection有关,我对其他例子有点困惑。
谢谢。
这听起来对依赖项注入很有用。与其给路由器一个要使用的类的字符串引用,为什么不简单地在构造函数中给它一个类本身的实例呢?
interface IForm { }
class frmLogin : Form, IForm { }
class frmDashboard: Form, IForm { }
class frmReport: Form, IForm { }
public class Router
{
IForm form;
public Router(IForm form)
{
this.form = form;
this.form.Index();
}
}
现在如何创建路由器?例如,通过使用FormFactory
然后调用new Router(myFactory.CreateForm("frmLogin"))
。
class FormFactory {
public IForm CreateForm(string name) {
switch(name) {
case: "frmLogin": return new frmLogin();
case: "frmDashboard": return new frmDashboard();
case: "frmReport": return new frmReport();
}
}
}
编辑:您也可以扩展您的工厂,只通过它们的名称来创建实例:
public IForm CreateForm(string name) {
return (IForm) Activator.CreateInstance(assembly, name);
}
但请注意,这将遵循动态程序集加载的工作流,包括完全限定的类型名称和程序集名称。请参阅此处CreateInstance
的使用方式。
EDIT2:在您编辑时,您希望每个类只有一个实例由路由器返回,因此您可以将表单设计为singletons:
class frmLogin : Form, IForm {
public static readonly Instance = new frmLogin();
private frmLogin() { }
}
现在工厂的方法稍微改变为这样:
var type = myAssembly.GetType(name);
return (IForm) type.GetField("Instance", BindingFlags.Public | BindingFlags.Static).GetValue(null);
这里有一个使用反射的解决方案,不过我建议使用一种更类型安全的方法,就像已经发布的方法一样。
它创建了一个字典,每个字段名和一个指向其相应索引方法的委托,因此在cctor运行期间,反射性能只会受到一次影响。
public static class Router
{
static frmLogin rLogin = new frmLogin();
static frmDashboard rDashboard = new frmDashboard();
static frmReport rReport = new frmReport();
static readonly Dictionary<string, Action> RoutingDictionary;
static Router()
{
RoutingDictionary = typeof (Router).GetFields(BindingFlags.Static | BindingFlags.NonPublic)
.Where(x => typeof (Form).IsAssignableFrom(x.FieldType))
.ToDictionary(k => k.Name, v =>
{
var form = v.GetValue(null);
return (Action) form.GetType().GetMethod("Index").CreateDelegate(typeof (Action), form);
});
}
public static void Route(string form)
{
RoutingDictionary[form]();
}
}