1

我已经阅读了许多试图完成类似任务的帖子,但找不到解决我问题的正确方法。

我正在尝试在运行时动态转换对象。(我知道你们很多人会说它不能完成,我实际上不确定它是否可以......)我的问题是我在 a 中动态创建TreeView了一个Windows Forms Application来显示一个Org Chart.

从 3 个表中TreeView提取的数据:DepartmentsJobsEmployees

Tables作为 a导入,Local DataSource我将所有 3 个表作为DataSet对象,并将对象类型的模板DataRow转换为它来自的表(包括作为属性的所有列)。(类似于 linq - Oracle DB 除外)

我创建TreeNode对象,使用我的描述字段DataRow作为TreeNode.Text属性,然后将其DataRow本身作为TreeNode.Tag属性。这样,我可以通过以下方式直接从内部访问数据TreeNode

dsMyDataSource.DepartmentRow = 
    (dsMyDataSource.DepartmentRow)treeview1.SelectedNode.Tag;

我有一个方法,只要用户选择一个填充一个带有一些基础对象数据的窗口Node的方法,它就会运行。截至目前,我有一个带有 switch 语句的方法,如下所示:treeview1Details

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);

问题是,这会返回一个基础对象(因此是演员表)。但我在编译时不知道用户将选择哪种类型的 TreeNode。因此,我希望能够执行以下操作:

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) {..}

这可能吗?

4

1 回答 1

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 ...
            }
    }
}

但是您现在拥有一组可以使用多态性来执行操作的 Selectable。

除了让您的生活更轻松之外,它还将使您的代码更容易为将来必须处理它的任何其他人解析。它也是可扩展的,因此当您需要添加 DoSomethingElse 方法时,添加所有内容要容易得多 - 或者当您需要一种新型数据表时,您不会干扰您的 UI 代码。

于 2013-02-05T21:10:05.123 回答