我已经阅读了许多试图完成类似任务的帖子,但无法找到解决问题的正确方法。
我正在尝试在运行时动态转换对象。 (我知道很多人会说它无法完成,我不确定它是否可以......)我的问题是我在{{{动态创建TreeView
1}}显示Windows Forms Application
。
Org Chart
中的数据来自3个表:TreeView
,Departments
,Jobs
。
将Employees
导入Tables
会将所有3个表格作为Local DataSource
个对象,并将DataSet
个对象的模板类型转换为它来自的表格(包括所有列作为属性)。 (与linq类似 - Oracle DB除外)
我创建DataRow
个对象,使用我的TreeNode
中的描述字段作为DataRow
属性,然后将TreeNode.Text
本身作为DataRow
属性附加。这样,我只需通过强制转换即可直接在TreeNode.Tag
内访问数据:
TreeNode
我有一个方法,只要用户在dsMyDataSource.DepartmentRow =
(dsMyDataSource.DepartmentRow)treeview1.SelectedNode.Tag;
上选择Node
,并使用某些基础对象数据填充treeview1
窗口,就会运行该方法。截至目前,我有一个带有switch语句的方法:
Details
我想要做的是为每种类型重载方法并摆脱我的switch语句。像这样:
private doSomething()
{
switch(treeview1.SelectedNode.Tag.GetType().Name)
{
case "dsMyDataSource.DepartmentRow":
dsMyDataSource.DepartmentRow department =
(dsMyDataSource.DepartmentRow)treeview1.SelectedNode.Tag;
lblDetailsTitle = department.Title;
break;
case "dsMyDataSource.JobRow":
//etc...
}
}
问题是,这会返回一个基础对象(因此是强制转换)。但我不知道在编译时用户将选择哪种类型的TreeNode。因此,我希望能够做到这样的事情:
this.doSomething(treeview1.SelectedNode.Tag);
这可能吗?
答案 0 :(得分:1)
如果您使用一些有意义的对象而不是直接使用DataRows,您可能会发现更清洁的东西。此外,这将允许您添加基类,这将使您的投射问题消失。
所以例如你可以
abstract class Selectable
{
public string Type { get; private set; }
public Selectable(string type) { Type = type; }
abstract void doSomething();
}
然后是您要选择的每件事的类型
class Department : Selectable{...}, class Job : Selectable{...}
要获得基本类型,您需要在工厂对象中使用一个开关。
public static class SelectableFactory
{
public static Selectable GetFromDataRow(DataRow dr)
{
Selectable res = null;
switch (dr.Type)
{
case "Department":
res = new Department(dr);
// etc ...
}
}
}
但是你现在有了一系列可以使用多态来执行操作的Selectables。
除了让您的生活更轻松之外,它还可以让您的代码更容易解析为将来必须处理它的任何其他人。它也是可扩展的,因此当您需要添加DoSomethingElse方法时,可以更轻松地添加所有内容 - 或者当您需要新类型的数据表时,不会打扰您的UI代码。