Question

Je suis face à un problème que je ne sais pas comment résoudre et espère que la communauté peut aider.

J'écris une application qui gère les objets « Lead ». (Ce sont des pistes de vente.) Une partie de mon programme va importer des pistes à partir d'un fichier texte. Maintenant, le fichier texte contient beaucoup de clients potentiels, dont certains je voudrai importer et dont certains je ne veux pas.

Pour faciliter la programmation (et l'utilisation), je suis l'analyse du fichier texte dans une liste objet, et en utilisant un DataGridView pour afficher les pistes en définissant la propriété DataSource du DataGridView.

Ce que je veux faire est d'ajouter une colonne à la grille, appelée « Importer », avec une case à cocher que l'utilisateur peut vérifier pour indiquer si oui ou non chaque plomb doit être importé.

Ma première pensée est de dériver une classe de plomb:

public Class LeadWithImportCheckbox : Lead
{
   bool bImport = false;

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

Cependant, le moteur d'analyse syntaxique retourne une liste d'objets en plomb. Je ne peux pas downcaster un plomb à un LeadWithImportCheckbox. Cela échoue:

LeadWithImportCheckbox newLead = (LeadWithImportCheckbox)LeadFromParsingEngine;
Ceci est une distribution non valide.

L'autre option que je vois est de créer un constructeur pour LeadWithImportCheckbox:

public LeadWithImportCheckbox(Lead newlead)
{
  base.Property1 = newlead.Property1;
  base.Property2 = newlead.Property2;
  ....
  base.Property_n = newlead.Property_n;
}
Cela pose problème pour deux raisons. Un, l'objet principal a plusieurs propriétés douzaine et la rédaction de ce constructeur est un PITA.

Mais le pire, si jamais je change la structure sous-jacente de plomb, je dois me rappeler de revenir en arrière et changer ce constructeur pour LeadWithImportCheckbox. Ceci est un danger pour mon entretien de code.

Y at-il une meilleure façon d'accomplir mon objectif?

Était-ce utile?

La solution

ou, pour éviter l'aspect PITA, la réflexion utiliser ... (essayer ...)

EDIT: propriété d'utilisation, pas de champ comme je l'avais écrit à l'origine ...

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

Autres conseils

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

i.e.. ne pas copier le contenu de l'objet principal, stocker juste une référence dans un nouvel objet LeadListItem, qui ajoute informations supplémentaires « en dehors » l'objet d'origine.

Si vous voulez que les propriétés de plomb à apparaître dans la grille, il y a certainement une façon de le faire. Pourquoi ne pas poser cette question, au lieu de me downvoting pour vous dire la bonne réponse à cette question!

A couple d'options que vous auriez pu manquer:

  • Vous pouvez mettre à jour l'objet principal lui-même d'avoir une propriété d'importation (qui par défaut à false).
  • Vous pouvez avoir votre « ImportLead » objet traiter le plomb comme charge utile (même le rendre générique, si vous voulez), de sorte que vous n'avez pas besoin du grand constructeur.
  • Construire une nouvelle liste d'objets de plomb ou dénombrable qui contient uniquement les objets que vous souhaitez importer en premier lieu.

Vous ne pouvez baissés, si l'objet est d'être baissés vraiment un objet de ce type.

Un moyen plus facile de résoudre votre problème serait d'avoir une classe DisplayLead, tels que:

  public class DisplayLead {
      Lead lead;
      bool bImport;
  }

qui aussi vous aider à séparer les données stockées à partir de leur représentation dans une interface graphique.

Qu'est-ce que vous voulez faire est d'afficher la colonne de cases à cocher sur votre grille et pas du tout ce lié à vos objets de plomb. Vous utilisez les colonnes marquées (et possible la liste originale) pour construire une nouvelle série de la liste qui sera votre liste d'importation.

MANIPULEZ tout ce que vous voulez faire avec la liste nouvellement créée.

Edit: Une chose à faire attention lorsque l'on travaille avec des listes est le fait chaque objet de classe est en fait seulement un pointeur vers la classe, donc si vous travaillez avec la liste initiale et de faire quelque chose comme:

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

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

que les objets existent dans les deux listes et si vous modifiez les données d'un responsable de chaque liste les deux seront changés.

Je ne peux pas baissés à quelque chose, ce n'est pas. Si l'objet est instancié comme Lead, il ne peut pas être baissés à une classe dérivée. Si elle était instancié comme LeadWithImportCheckbox puis est retourné à votre code comme Lead, alors vous pouvez downcaster il.

Protip: Vérifiez le type à l'exécution avec l'opérateur is

.

Il y a plusieurs façons de faire, mais le « droit » chemin ressorte à cause de ce que vous avez dit, ici:

  

Pour faciliter la programmation (et utilisation), je suis   l'analyse du fichier texte dans un   Liste objet, et en utilisant un   DataGridView pour afficher les fils de   définir la propriété DataSource du   DataGridView.

     

Ce que je veux faire est d'ajouter une colonne à   la grille, appelée « Importer », avec   case à cocher que l'utilisateur peut vérifier   indiquer si oui ou non chaque plomb   doivent être importés.

Votre objet Lead se tient bien sur elle-même, et que vous souhaitez attacher des métadonnées à - vous ne voulez pas créer une autre classification Lead (à savoir la classe LeadWithImportCheckbox)

.

Alors, la meilleure approche dans votre cas est d'avoir une classe comme ceci:

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

Cela échelle bien quand vous voulez ajouter des métadonnées à votre liste, comme si vous voulez vous envoyer des e-mail des rappels sur eux chaque semaine.

Je l'ai vu la solution correcte énuméré tant de fois je me sens comme un affichage talon encore, mais la meilleure façon de procéder est d'écrire un wrapper pour l'objet principal qui comprend le drapeau d'importation.

Si les propriétés de l'objet principal ne figurent pas dans le GridView parce que vous êtes à l'objet databinding, puis d'écrire des propriétés passthrough qui reflètent les propriétés de plomb sur l'objet wrapper.

Le problème est que vous voulez quelque chose affiché à l'utilisateur qui ne fait pas partie intégrante du modèle de données. La réponse est d'envelopper les données avant de le présenter à l'utilisateur de sorte que vous pouvez contrôler ce qu'ils voient sans changer le modèle sous-jacent.

Si vous craignez que l'objet principal changera tant de fois à l'avenir qui change de l'emballage sera lourd, vous pouvez regarder dans la génération de code dynamique basé sur l'objet principal qui génère automatiquement un objet wrapper avec le mêmes champs que l'objet principal, plus le drapeau d'importation. Bien franchement, c'est beaucoup plus de travail que vous aurez besoin probablement pour quelque chose d'aussi simple que cela.

En tant que solution rapide et sale, vous pouvez créer votre objet « case » comme un autre objet contenant une instance de plomb.

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

De cette façon, vous pouvez facilement ajouter des propriétés plus « grille » à cet objet, tout en conservant toujours une référence aux détails sans plomb hardcoding clonage de la propriété en elle.

vous recommandons d'essayer de modifier (mise à niveau) vos objets de plomb importés.

Essayez en commençant par les exemples ...

Si votre classe Lead avait un constructeur de copie (par exemple « plomb (otherLead) »), LeadWithImportCheckbox hériterait que et vous pouvez simplement appeler la base constructeur de plomb dans le constructeur LeadWithImportCheckbox - donc pas besoin de LeadWithImportCheckbox d'être au courant de la détails de plomb.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top