使用GetType()的C#动态铸造
本文关键字:动态 GetType 使用 | 更新日期: 2023-09-27 17:58:05
我读过很多试图完成类似任务的帖子,但找不到合适的解决方案。
我正在尝试在运行时动态地转换一个对象。(我知道你们中的很多人会说这是不可能的,我实际上不确定它是否可以…)我的问题是,我在Windows Forms Application
中有一个动态创建的TreeView
来显示Org Chart
。
TreeView
中的数据来自3个表:Departments
、Jobs
、Employees
。
将Tables
导入为Local DataSource
会将所有3个表作为DataSet
对象,并将DataRow
对象的模板类型转换为它所来自的表(包括作为属性的所有列)。(类似于linq-除了Oracle数据库)
我创建TreeNode
对象,使用DataRow
中的描述字段作为TreeNode.Text
属性,然后将DataRow
本身附加为TreeNode.Tag
属性。这样,我可以直接在TreeNode
中访问数据,只需铸造:
dsMyDataSource.DepartmentRow =
(dsMyDataSource.DepartmentRow)treeview1.SelectedNode.Tag;
我有一个方法,每当用户在treeview1
上选择一个Node
时就会运行,该方法会用一些底层对象数据填充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...
}
}
我想做的是为每种类型都重载方法,并去掉我的switch语句。像这样:
this.doSomething(treeview1.SelectedNode.Tag);
问题是,这会返回一个基对象(从而返回强制转换)。但我不知道在编译时用户会选择什么类型的树节点。因此,我希望能够做一些类似的事情:
this.doSomething((treeview1.SelectedNode.Tag.GetType())treeview1.SelectedNode.Tag);
private void doSomething(dsMyDataSource.DepartmentRow department)
{
lblDetailsTitle = department.Title;
// etc...
}
private void doSomething(dsMyDataSource.JobRow job) {..}
private void doSomething(dsMyDataSource.EmployeeRow employee) {..}
这可能吗?
如果您使用一些有意义的对象,而不是直接从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{...}
要获得基本类型,您需要在factory对象中使用一个开关。
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代码。