2016-09-20 6 views
0

クラスをベースインターフェイスにダウンコンバートする際に問題があります。私は(簡体字)、次があります。ジェネリックタイプのインターフェイスでクラスからインターフェイスに変換するインターフェイス<Interface>

public interface ITaxonomy 
{ 
    string CommonName { get; set; } 
    string ScientificName { get; set; } 
} 

public interface ITaxonomyHasChildren<TChild> : ITaxonomy where TChild : ITaxonomy 
{ 
    ICollection<TChild> Children { get; set; } 
} 

public interface ITaxonomyHasParent<TParent> : ITaxonomy where TParent : ITaxonomy 
{ 
    TParent Parent { get; set; } 
} 

をそして私は私のVMに出て戻ってデータを抽出する必要があります。

private void SelectedEntityChanged(ITaxonomy selectedEntity) 
{ 
    CommonName = selectedEntity.CommonName; 
    ScientificName = selectedEntity.ScientificName; 

    Children = selectedEntity.GetType().GetProperty(nameof(ITaxonomyHasChildren<ITaxonomy>.Children))? 
     .GetValue(selectedEntity) as ICollection<ITaxonomy>; 

    Parent = selectedEntity.GetType().GetProperty(nameof(ITaxonomyHasParent<ITaxonomy>.Parent))? 
     .GetValue(selectedEntity) as ITaxonomy; 
} 

Children一部が動作しない、それはをdoesnのため、私は想定していますtをICollection<MyClass>からICollection<ITaxonomy>に変更すると、

どのようにすればいいですか?

+0

が展開し、 "動作しない"、例外はありますか?期待される行動は何か。 – raidensan

答えて

4

これを機能させるには、汎用インターフェイスを作成する必要がありますcovariant。しかし、ICollection<T>は共変ではないので、ChildrenのタイプをIReadOnlyCollection<TChild>に変更し、それを買う人がいる場合はセッターを削除する必要があります。

public interface ITaxonomyHasChildren<out TChild> : ITaxonomy where TChild : ITaxonomy 
{ 
    IReadOnlyCollection<TChild> Children { get; } 
} 

public interface ITaxonomyHasParent<out TParent> : ITaxonomy where TParent : ITaxonomy 
{ 
    TParent Parent { get; } 
} 

これはまた、あなたが反射を避けるためにできるようになります:

private void SelectedEntityChanged(ITaxonomy selectedEntity) 
{ 
    CommonName = selectedEntity.CommonName; 
    ScientificName = selectedEntity.ScientificName; 

    Children = (selectedEntity as ITaxonomyHasChildren<ITaxonomy>)?.Children; 
    Parent = (selectedEntity as ITaxonomyHasParent<ITaxonomy>)?.Parent; 
} 

サンプルクラスの実装:

selectedEntity.GetType() 
    .GetProperty(nameof(ITaxonomyHasChildren<ITaxonomy>.Children)) 
    .GetValue(selectedEntity) 

を起動

class Taxonomy : ITaxonomy, ITaxonomyHasChildren<Taxonomy>, ITaxonomyHasParent<Taxonomy> 
{ 
    public string CommonName { get; set; } 
    public string ScientificName { get; set; } 
    public Taxonomy Parent { get; set; } 
    public List<Taxonomy> Children { get; set; } = new List<Taxonomy>(); 
    IReadOnlyCollection<Taxonomy> ITaxonomyHasChildren<Taxonomy>.Children => Children; 
} 
+0

'ICollection 'は共変ではなく、セッターを保持することはできません。 – Lee

+0

@Lee同じことを実現しました。 –

+0

ありがとう、私はこれを念頭に置いておきます - これらのアイテムはすべて実行時に編集可能になるため、アイテムを読み込み専用にするという考えは本当に好きではありませんが、私が避けたいと思う余分な仕事をたくさん追加するだけです。 –

2

はやっての非常に回り道でありますもの。

基本的なオブジェクト指向のものを達成するために反射システムを使用する必要はありません。

また、正当な理由がないため、あなたのタイプは非常に複雑です。

代わりにこれを考えてみましょう:

public interface IParent<T> //note: general-purpose interface unrelated to taxonomies 
{ 
    ICollection<T> Children { get; } 
} 

public interface IChild<T> //note: general-purpose interface unrelated to taxonomies 
{ 
    T Parent { get; set; } 
} 

public interface ITaxonomy 
{ 
    string CommonName { get; set; } 
    string ScientificName { get; set; } 
    IParent<ITaxonomy> AsParent {get; } //returns `null` if not a parent 
    IChild<ITaxonomy> AsChild {get; } //returns `null` if not a child 
} 

IChild<ITaxonomy> selectedEntityAsChild = selectedEntity.AsChild; 
if(selectedEntityAsChild != null) 
{ 
    ITaxonomy parent = selectedEntityAsChild.Parent; 
    ... 
} 

IParent<ITaxonomy> selectedEntityAsParent = selectedEntity.AsParent; 
if(selectedEntityAsParent != null) 
{ 
    ICollection<ITaxonomy> children = selectedEntityAsParent.Children; 
    ... 
} 
+0

すべてのタクソノミーが両親や子供を持っているわけではありません。 –

+0

@AnthonyNicholsもちろん、AsParentゲッターは、呼び出すタクソノミが親ではない場合、例コードが示すように、 'null'を返します。 –

+0

また、 'class MyParentTaxonomy:ITaxonomy、IParent 'と宣言し、 'selectedEntityAsParent = selectedEntity as IParent 'を実行するオプションがありますが、それはもっと謎です。 –

関連する問題