2009-07-15 9 views
6

私は解決方法がわからず、コミュニティが助けてくれることを望んでいるという問題に直面しています。Cでのダウンキャスト

「リード」オブジェクトを管理するアプリを作成しています。 (これらは販売リードです。)私のプログラムの一部は、テキストファイルからリードをインポートします。現在、テキストファイルには多くの潜在的なリードが含まれていますが、そのうちのいくつかはインポートしたいものと、そうでないものがあります。

簡単にプログラミング(および使用)するために、テキストファイルをList <リードオブジェクトに解析し、DataGridViewを使用して、DataGridViewのDataSourceプロパティを設定してリードを表示します。

「インポート」というグリッドに列を追加するには、各リードをインポートする必要があるかどうかをユーザーがチェックできるチェックボックスを付けます。

私が最初に考えたのは、リードからクラスを派生することです:

 
public Class LeadWithImportCheckbox : Lead 
{ 
    bool bImport = false;

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

しかし、構文解析エンジンは、リードオブジェクトのリストを返します。鉛をLeadWithImportCheckboxに降格することはできません。これは失敗します:

 
LeadWithImportCheckbox newLead = (LeadWithImportCheckbox)LeadFromParsingEngine; 
これは無効なキャストです。

私が見る他のオプションは、LeadWithImportCheckboxのコンストラクタを作成することです:

 
public LeadWithImportCheckbox(Lead newlead) 
{ 
    base.Property1 = newlead.Property1; 
    base.Property2 = newlead.Property2; 
    .... 
    base.Property_n = newlead.Property_n; 
} 
これは、2つの理由から問題です。 1つ目は、Leadオブジェクトには数十のプロパティがあり、このコンストラクタを書くことはPITAです。

さらに悪いことに、Leadの基本構造を変更した場合は、このコンストラクターをLeadWithImportCheckboxに変更することを忘れないでください。これは私のコード管理の危険です。

私の目標を達成する良い方法はありますか?

+0

ランダムな考え:リードが「インポート」されているかどうか(手動入力済み)を追跡することができますか?言い換えれば、「鉛」の永久財産を「輸入」することは実現可能なのだろうか? – Adrien

+0

私はそれが私が追跡したいと思うだろうとは思わない。私はこれで解決できる問題を見ていますが、実際に達成したいことの一部ではありません。 –

答えて

6

または、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); 
    } 
} 
+0

私は最終的に反射アプローチが好きだと思います。 (私は理解が不足しています。)サンプルコードでは、typeof(Lead).GetFields()から長さゼロの配列を取得します。 –

+0

これは私が解決しようとしているソリューションだと思います。ありがとう、チャールズ!私が実装し、動作するように見えるコードは以下の通りです:

 public LeadWithImportCheckbox(Lead lead):base() { Type LeadType = typeof(Lead); PropertyInfo[] properties = LeadType.GetProperties(); foreach (PropertyInfo fi in properties) { object value = fi.GetValue(lead, null); fi.SetValue(this, value, null); } } 

+0

素晴らしい解決策です。基本クラスが変更された場合、私のコンストラクタを手動で更新する必要はありません。 – jocull

1

あなたがしたいことは、グリッドにチェックボックスの列を表示し、リードオブジェクトにはまったく関係しません。マークされた列(および元のリスト)を使用して、インポートリストになる新しいリストセットを作成します。

次に、新しく作成されたリストで何をしたいかを処理します。

編集:リストで作業する場合の注意する一つのことは、あなたが元のリストと協力し、ような何かを行うので、もしすべてのクラスオブジェクトが実際にクラスへのポインタのみであるという事実である:

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

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

そのオブジェクトは両方のリストに存在し、どちらのリストでもリードのデータを編集すると両方が変更されます。

+0

私はもともとこの解決策を追求しました。 List を使用すると適切に動作します。ただし、SortableBindingList ラッパーを使用すると、DataGridViewがソートされているときにチェックマークがリードに残りません。テキストファイルには〜1000の潜在的なリードがあるので、ソートが重要です。 (私は元の問題文でこれを含めないことをお詫びします;どのくらいの情報が十分であるかは分かりませんが、ポストを簡素化するにはそれほど多すぎない) –

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

つまりはただの余分な情報「外」元のオブジェクトを追加する新しいLeadListItemオブジェクトにそれへの参照を格納し、リードオブジェクトの内容をコピーしないでください。

グリッドに[リード]のプロパティを表示したい場合は、その方法がほぼ確実です。なぜあなたはこの質問への正しい答えを伝えるために私にdownvotingの代わりに、その質問をしないでください!

+0

このソリューションの問題は、Leadのメンバーが表示されないということですDataGridViewでデータを取得します。 –

+0

@ Demigeekできることは確かですが、それは別の質問です。 – exclsr

+0

GreenReign、別の質問はどうですか?元の質問は、DataGridViewにチェックボックス付きのリードを表示することでした。 DataGridViewにLeadのメンバーを含まないソリューションは、この問題の解決策ではありません。 –

3

カップルのオプションあなたが見逃している可能性があります:

  • インポート性がリードオブジェクト自体を更新でき(そのデフォルトはfalse)。
  • "ImportLead"オブジェクトでリードをペイロードとして扱うこともできます(必要に応じて一般化することもできます)ので、大きなコンストラクタは必要ありません。
  • 最初にインポートするオブジェクトのみを含む新しいリードオブジェクトリストまたは列挙型を作成します。
+0

私はリードクラスそのものにImportプロパティを作ることになるだろう –

+0

もっと雄弁に上記の私の不器用な試みよりも、私が言おうとしていたことはかなり言いました。 – Adrien

+4

私はStanに同意しなければならないでしょう。鉛にインポートプロパティがある理由はありません。鉛にはまったく関係がなく、ドメインオブジェクトの汚染です。それは唯一のUIアーティファクトなので、とにかくあなたのドメインオブジェクトを変更すべきではありません。 –

1

ダウンキャストされるオブジェクトがの場合、実際にはそのタイプのオブジェクトであるです。

など、DisplayLeadクラスを持っているだろう、あなたの問題を解決する簡単な方法:また、あなたはGUIでの表現から格納されたデータを分離することに役立つだろう

public class DisplayLead { 
     Lead lead; 
     bool bImport; 
    } 

+0

これを行うと、鉛のプロパティがDataGridViewに表示されません。 –

+1

私の投稿に応じてあなたが提供した情報で、これが最適な解決策です。実行する必要があるのは、列の自動生成をオフにし、手動で列を作成し、データバインディング式を使用して実際のコンテナ項目に到達する必要があるため、複雑なオブジェクトを読み取ることができます。 C#Databinding Evalまたはそれに類するものをGoogleで検索するには、その方法を理解する必要があります。 –

0

迅速で汚れた解決策として、リードのインスタンスを含む別のオブジェクトとして 'チェックボックス'オブジェクトを作成することができます。

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

まだ常にそれへのクローニングのプロパティをハードコーディングせずにリードの詳細への参照を保持したまま、簡単に、このオブジェクトにより「グリッドのプロパティを追加することができますこの方法。

+0

これを行うと、鉛のプロパティがDataGridViewに表示されません。 –

0

インポートしたリードオブジェクトを変更(アップグレード)することをおすすめします。

は、私はそれがないものにダウンキャストすることはできません...例hereで始まる

1

を試してみてください。オブジェクトがLeadとしてインスタンス化されている場合は、派生クラスにダウンキャストできません。 LeadWithImportCheckboxとしてインスタンス化され、コードにLeadとして返された場合、それをダウンキャストすることができます。

Protip:タイ​​プを実行時にisオペレータでチェックしてください。

0

Leadクラスにコピーコンストラクタ( "Lead(lead otherLead)"など)がある場合、LeadWithImportCheckboxはそれを継承し、LeadWithImportCheckboxコンストラクタの基本Leadコンストラクタを呼び出すことができます。鉛の詳細

1

は、これを行うには多くの方法がありますが、「正しい」方法は、ここでは、理由はあなたが言ったことの飛び出し:

は、プログラミング(および使用)を容易にするため、私は、テキストを解析 よファイルを Listオブジェクトに挿入し、 DataGridViewを使用して、 によってLeadを表示し、 DataGridViewのDataSourceプロパティを設定します。

私は何をしたいユーザーは に確認することができ チェックボックスで「インポート」と呼ばれる、 にグリッドを列を追加され をインポートする必要がつながるかどうかをそれぞれ示しています。

あなた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; } 
    } 
} 

あなたはあなた自身が電子メール送信する場合のように、あなたのリストに多くのメタデータを追加したい時にこれがうまくスケールします毎週彼らのことを思い出させます。

+0

これを行うと、LeadプロパティはDataGridViewに表示されません。 –

1

私は正しいソリューションが何度もリストされていることを見てきましたが、私はヒールのように再投稿したいと思っていますが、これにアプローチする最も良い方法は、インポートフラグを含むLeadオブジェクトのラッパーを書くことです。

オブジェクトにデータバインドしているために、リードオブジェクトのプロパティがGridViewに表示されない場合は、ラッパーオブジェクトのリードプロパティを反映するパススループロパティを作成します。

問題は、データモデルの本質的な部分ではないものがユーザーに表示されるようにすることです。答えは、データをユーザーに提示する前にラップして、基礎となるモデルを変更せずに表示内容を制御できるようにすることです。

将来、リードオブジェクトが何度も変更されてラッパーの変更が煩雑になることが懸念される場合は、リードオブジェクトに基づいて動的なコード生成を調べると、自動的にラッパーオブジェクトを生成しますLeadオブジェクトと同じフィールドとインポートフラグ。率直に言って、それはあなたがこれほど簡単なもののためにおそらく必要とするよりもはるかに多くの仕事です。

+0

これは最適な解決策だとは思わない。 Leadオブジェクトの構造が変更された場合は、LeadのプロパティをDataGridViewにバインドするコードを編集して編集する必要があります。 継承はこの問題を解決します。 Leadへの変更が何であっても、LeadWithImportCheckboxがLeadから継承する場合、コードを変更する必要はありません。そして 'LeadThatIMightWantToImport'はIs-A 'Lead'です。継承が適切です。 チャールズが示唆しているように、Reflectionを使用することは、リードからLeadWithImportCheckboxを作成する正しい方法になると思います。 –

+0

リフレクトアプローチは、「基礎となるリードオブジェクトの変更」の問題を緩和しますが、Leadオブジェクトが頻繁にそれを変更している場合は、コーディングのプラクティスよりも深刻な問題があります。チャールズの解決策へのあなたの反応に基づいて、私は反射があなたのために行く正しい方法になるとは思っていません。また、このようにリフレクションを使用すると、深刻なパフォーマンス上のペナルティが課せられます(何千ものリードを開始すると問題になる可能性があります)。 – genki

関連する問題