2017-01-20 3 views
1

私は同様の質問に対する他の回答を見直しましたが、私が欲しいものを正確に見つけることはできません。私は2つのサブクラスのいずれかのインスタンスを格納できるSuperclass型の辞書を持っています。サブクラスの1つのメンバーにアクセスできる必要があります。私はそれにアクセスするためにサブクラスにLINQクエリでキャストする方法を把握することができません。ここに私が持っているものがあります。LINQクエリ内のサブタイプにキャスト

class VirtualFabric 
{ Dictionary<string, SANSwitch} MemberSwitches = new Dictionary<string, SANSwitch>();  

class SANSwitch 
{ 
    string SwitchWWN {get; set; } 
    Dictionary<int, VirtualFabric> VirtualFabrics = new Dictionary<int, VirtualFabric>(); 
} 

class CiscoSwitch : SanSwitch {} 
class BrocadeSwitch : SanSwitch 
{ 
public Dictionary<int, string> VirtualWWNList = new Dictionary<int, string>(); 

    public bool HasWWN(string wwn) 
    { 
     if (wwn.StartsWith("55")) { return this.VirtualWWNList.Values.Contains(wwn); } 
     else { return this.SwitchWWPN.Contains(wwn); } 
    }  
} 

したがって、VirtualFabricのMemberSwitchesは、CiscoSwitchまたはBrocadeSwitchのインスタンスを保存できます。私はこれをやろうとしている:HasWWNは()SANSwitch BrocadeSwitchにしていない定義されているため

List<SwitchPort> isls = this.ISLs.SelectMany(p => p.Value.Where(i => i is FCPort)).ToList(); 

     // set up the ISLs 
     // if the remote switch port list already contains a port, then that switch log has been processed 
     // so do nothing 

foreach (SwitchPort p in isls) 
{ 
    var bs = this.VirtualFabricList.SelectMany(t => t.Value.MemberSwitches.Values.Where 
(s => s.Value.HasWWN(p.RemoteSwitchWWPN))); 

// do something with any results 
} // foreach 

SelectManyがコンパイルされていません。私はそれをSANSwitchに移すことができるが、したくない。また、BrocadeタイプのMemberSwitches内のすべてのスイッチを取得したり、繰り返してBrocadeとして宣言してからそのリストを検索したりすることもできますが、LINQステートメントでキャストする方法があるかどうかは疑問です。私は特定のタイプのSelectの例を見ましたが、それは私が望むものではありません。ここで

+0

あなたが1つのクラスをキャストできるならば、あなたは私が知っている新しいリスト –

+0

にすべてをキャストするために 'Select'を使うことができます。私はそれを避け、おそらく何かを学ぶことを望んでいました。 –

+0

[Enumerable.OfType メソッド(IEnumerable)](https://msdn.microsoft.com/en-us/library/bb360913) – Slai

答えて

0

は別のクラスを派生クラスである:ここでは

public class Class1 { } 

public class Class2 : Class1 { 
    public List<Class2> Twos { get { return new List<Class2>(); } } 
} 

はキャストする方法である:

var c1 = new Class2(); 
var c2 = new Class2(); 
var l = new List<Class2> { c1, c2 }; 
var ints = l.SelectMany(x => x.Twos).Cast<Class1>(); 

それとも、代わりにこのように、各オブジェクトをキャストの列挙子をキャスト:

var ints = l.SelectMany(x => x.Twos) as IEnumerable<Class1>; 

Class2Class1を派生しているので、キャストを行うことができます。しかし、Class1からClass2にキャストしようとすると、Class2がより具体的であるため失敗します。

var bs = this.VirtualFabricList.SelectMany(t => t.Value.MemberSwitches.Values.Where 
(s => s.Value.HasWWN(p.RemoteSwitchWWPN))); 

MemberSwithches.ValuesSANSwitchを返し、その後、あなたがHasWWNメソッドを持っていないs.Value.HasWWN方法が、CiscoSwitchを呼び出そうとしている:

EDITあなたは、このラムダを持っています。それをしてはいけない。これを行う必要があります:

var bs = this.VirtualFabricList.SelectMany(t => t.Value.MemberSwitches.Values 
    .Where(s => s.Value is BrodcadeSwitch)).Cast<BrodcadeSwitch>() 
    .Where(s => s.HasWWN(p.RemoteSwitchWWPN)); 
+0

ok。あなたの例を使用して私はClass2(派生クラス)からClass1にキャストしようとしています。だから私は代わりに選択の前にキャストを行う必要があります。 –

+0

いいえ、もっと明確にするために私の編集を参照してください。 – CodingYoshi

0

VirtualFabricListの種類を記述するのを忘れました。

linq文から、VirtualFabricListの各「t」にはVirtualFabricクラスにないプロパティValueがあるため、VirtualFabricListは一連のVirtualFabricオブジェクトではないことがわかります。

しかし、残りのlinqから、私はそれぞれのt.ValueがVirtualFabricであることを確認します。さらに、各t.Valueには、SANSwitchオブジェクトを含むディクショナリであるMemberSwitchesというプロパティがあります。

辞書には、BrocadeSwitchオブジェクトである辞書のSANSスイッチのみが必要です。また、すべてのBrocadeSwitchesではなく、HasWwn(...)が真を返すものだけです。

問題は、BrocadeSwitchのみチェックできるだけで、HasWWNのSANSwitchesの辞書のすべての要素をチェックすることです。

IEnumerable<VirtualFabric> virtualFabrics = this.VirtualFabricList 
    .Select(t => t.Value>); 
IEnumerable<Dictionary<string, SANSwitch>> dictionaries = virtualFabrics 
    .Select(fabric => fabric.MemberSwitches); 
IEnumerable<SanSwitch> sanSwitches = dictionaries 
    .SelectMany(dictionary => dictionary.Values); 

注:このためには、小さなステップでEnumerable.OfType

を使用することができ、あなたのVirtualFacbricListについての私の推測が正しくない場合、SanSwitchオブジェクトのシーケンスを取得するために、独自のステートメントを使用します。この配列から、あなたはBrocadeSwitches得ることができます:

IEnumerable<SanSwitch> sanSwitches = ... 
IEnumerable<BrocadeSwitch> brocadeSwitches = sanSwitches.OfType<BrocadeSwitch>(); 
IEnumerable<BrocadeSwitch> switchesWithWWN = brocadeSwitches 
    .Select(brocadeSwitch => brocadeSwitch.HasWWN(...) 

をだから、重要な特徴は、あるEnumerable.OfType

これらの小さなステップを使用すると、各LINQ文は、あなたが期待する項目が含まれていることを確認するのに役立ちます。あなたのプロセスを遅くすることはありません。遅延実行のため、これらのステートメントはあなたのToList()まで実行されません。

もちろん、可読性とデバッグ能力があなたの優先順位リストで最高でない場合は、これらのステートメントを1つの大きなlinqステートメントに入れることができます。

関連する問題