在C#中向下倾斜

时间:2009-07-15 18:56:59

标签: c# inheritance downcast

我遇到一个我不知道如何解决的问题,希望社区可以提供帮助。

我正在编写一个管理“潜在客户”对象的应用。 (这些是销售线索。)我的程序的一部分将从文本文件中导入潜在客户。现在,文本文件包含许多潜在的潜在客户,其中一些我想要导入,其中一些我不会。

为了便于编程(和使用),我正在将文本文件解析为List< Lead>对象,并使用DataGridView通过设置DataGridView的DataSource属性来显示引线。

我想要做的是在网格中添加一个名为“导入”的列,其中包含一个复选框,用户可以选中该复选框以指示是否应导入每个导联。

我的第一个想法是从Lead派生一个班级:

public Class LeadWithImportCheckbox : Lead
{
   bool bImport = false;

public bool Import { get { return bImport;} set { bImport = value;} } }

但是,解析引擎会返回Lead对象列表。我无法将潜在客户转向LeadWithImportCheckbox。这失败了:

LeadWithImportCheckbox newLead = (LeadWithImportCheckbox)LeadFromParsingEngine;
这是无效的演员。

我看到的另一个选项是为LeadWithImportCheckbox创建一个构造函数:

public LeadWithImportCheckbox(Lead newlead)
{
  base.Property1 = newlead.Property1;
  base.Property2 = newlead.Property2;
  ....
  base.Property_n = newlead.Property_n;
}
出于两个原因,这是有问题的。一,Lead对象有几十个属性,编写这个构造函数是PITA。

但更糟糕的是,如果我更改了Lead的底层结构,我需要记住返回并更改LeadWithImportCheckbox的构造函数。这对我的代码维护是一种危险。

有没有更好的方法来实现我的目标?

11 个答案:

答案 0 :(得分:7)

或者,为避免PITA方面,请使用反射...(试试这个......)

编辑:使用属性,而不是我最初写的字段......

public class NewLead : Lead
{
    public bool Insert;
    public NewLead(Lead lead, bool insert)
    {
        Insert = insert;
        foreach (PropertyInfo pi in typeof(Lead).GetProperties())
            GetType().GetProperty(pi.Name).SetValue
               (this, pi.GetValue(lead,null), null);
    }
}

答案 1 :(得分:4)

public class LeadListItem
{
    public Lead Lead { get; set; }
    public bool ShouldImport { get; set; }
}

即。不要复制Lead对象的内容,只需在新的LeadListItem对象中存储对它的引用,这会在原始对象“之外”添加额外的信息。

如果您希望Lead的属性出现在网格中,几乎可以肯定有一种方法可以实现。为什么不问这个问题,而不是低估我告诉你这个问题的正确答案!

答案 2 :(得分:3)

您可能错过了几个选项:

  • 您可以将Lead对象本身更新为具有Import属性(默认为false)。
  • 您可以让“ImportLead”对象将Lead视为有效负载(如果需要,甚至将其设为通用),这样您就不需要大型构造函数。
  • 构建一个新的Lead对象列表或可枚举的列表,它只包含您想要首先导入的对象。

答案 3 :(得分:1)

您要执行的操作是显示网格上的复选框列,而不是与Lead对象完全相关。您可以使用标记的列(以及可能的原始列表)来构建一组新的List,它将作为您的导入列表。

然后处理你想用新创建的List做的任何事情。

编辑:使用列表时要注意的一件事是每个类对象实际上只是指向类的指针,所以如果你使用原始列表并执行以下操作:

List<Lead> Importable = new List<Lead>();

for(int i=0, i++, i<viewGrid.Count)
    if(viewGrid[i].CheckedColumn.Checked)
        Importable.Add(OriginalList[i]);

两个列表中都存在这些对象,如果您在任一列表中编辑Lead的数据,则两者都将被更改。

答案 4 :(得分:1)

如果要转发的对象真的是该类型的对象,则只能向下转发。

解决问题的一种更简单的方法是使用DisplayLead类,例如:

  public class DisplayLead {
      Lead lead;
      bool bImport;
  }

还可以帮助您将存储的数据与GUI中的表示分开。

答案 5 :(得分:1)

我不能贬低它不是的东西。如果对象被实例化为Lead,那么它不能被转发到任何派生类。如果它被实例化为LeadWithImportCheckbox,然后以Lead的形式返回到您的代码,那么您可以向下转发它。

Protip:使用is运算符在运行时检查类型。

答案 6 :(得分:1)

有很多方法可以做到这一点,但由于你说的话,“正确”的方式会突然出现:

  

为了便于编程(和使用),我是   将文本文件解析为   列出对象,并使用   DataGridView显示引线   设置的DataSource属性   的DataGridView。

     

我想要做的是添加一列   网格,称为“导入”,带有   用户可以检查的复选框   表明每个领导   应该进口。

您的Lead对象本身就很好,并且您想要附加一些元数据 - 您不想创建另一个Lead分类(即LeadWithImportCheckbox类)。

因此,在您的情况下,最好的方法是拥有一个类似的类:

public class LeadInfo 
{
    private Lead lead;
    private bool shouldImport;

    public LeadInfo(Lead lead)
    {
        this.lead = lead;
        this.ShouldImport = false;
    }

    public bool ShouldImport 
    { 
        get { return shouldImport;  }
        set { shouldImport = value; }  
    }
}

如果您想要在列表中添加更多元数据,这可以很好地扩展,例如,如果您想每周向自己发送有关它们的电子邮件提醒。

答案 7 :(得分:1)

我已经看过很多次列出的正确解决方案,我觉得它再次发布了,但最好的办法就是为包含导入标志的Lead对象编写一个包装器。

如果Lead对象的属性没有出现在GridView中,因为您正在对该对象进行数据绑定,那么请写入镜像包装器对象上的Lead属性的passthrough属性。

问题是您希望向用户显示的内容不是数据模型的固有部分。答案是在将数据呈现给用户之前将数据包装起来,这样您就可以控制他们看到的内容,而无需更改基础模型。

如果你担心Lead对象将来会改变很多次,那么对包装器的更改会很麻烦,你可以看一下基于Lead对象的动态代码生成,它会自动生成一个包装器对象。与Lead对象相同的字段加上导入标志。坦率地说,这比你可能需要的工作要多得多。

答案 8 :(得分:0)

作为一种快速而肮脏的解决方案,您可以将“复选框”对象创建为包含Lead实例的其他对象。

public GridLead {
   public bool Import { get; set; }
   public Lead Lead { get; set; }
}

通过这种方式,您可以轻松地向此对象添加更多“网格”属性,同时始终保留对Lead详细信息的引用,而无需将硬编码属性克隆到其中。

答案 9 :(得分:0)

建议您尝试修改(升级)导入的潜在客户对象。

尝试从示例here ...

开始

答案 10 :(得分:0)

如果你的Lead类有一个拷贝构造函数(例如“Lead(Lead otherLead)”),那么LeadWithImportCheckbox会继承它,你可以在LeadWithImportCheckbox构造函数中调用基础Lead构造函数 - 因此LeadWithImportCheckbox不需要知道Lead的详细信息。