2017-08-25 11 views
0

私は、パラメータとして渡されたインターフェイスの実装に応じて、クラスのインスタンスを作成したいという状況があります。returnを理解する基本パラメータとしてジェネリックパラメータを持つDerivedクラス

public interface IFooParameters 
{ 
    int Id { get; } 
} 

public interface IFooParametersAdditional 
{ 
    int AnotherProperty { get; } 
} 

public class FooBarParameters : IFooParameters 
{ 
    public int Id { get; set; } = 1; 
    public int Bar { get; set; } = 42; 
} 

public class FooBazParameters : FooBarParameters, IFooParametersAdditional 
{ 
    public int Baz { get; set; } = 55; 
    public int AnotherProperty { get; set; } = 99; 
} 

public interface IFoo<in TFooParameters> 
    where TFooParameters : IFooParameters 
{ 
    void DoStuff(TFooParameters parameters); 
} 

public class Bar : IFoo<FooBarParameters> 
{ 
    public void DoStuff(FooBarParameters parameters) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public class Baz : IFoo<FooBazParameters> 
{ 
    public void DoStuff(FooBazParameters parameters) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public class Another : IFoo<FooBazParameters> 
{ 
    public void DoStuff(FooBazParameters parameters) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

public interface IFooFactory 
{ 
    IFoo<IFooParameters> GetInstance(IFooParameters parameters); 
} 

public class FooFactory : IFooFactory 
{ 
    public IFoo<IFooParameters> GetInstance(IFooParameters parameters) 
    { 
     if (parameters.Id == 1) 
      return new Bar(); // *** compiler error 

     if (parameters.Id == 2) 
      return new Baz(); // *** compiler error 

     return new Another(); // *** compiler error 
    } 
} 

// *** compiler errorです:

エラーCS0266は、暗黙的に'IFoo<IFooParameters>'にタイプ'Bar'を変換できません。明示的な変換は、私はこれを取得、なぜ私は、派生実装がは(私は考えを持っているでしょう)、暗黙的にBar : IFoo<FooBarParameters>としてそれらのベースに変換する必要があります思ったように私は、よく分からない(あなたはキャストが欠けている?)

が存在しますそしてFooBarParameters : IFooParameters、これは(ジェネリックを持ち込むことではない)作品:私は達成するために願っています何の背後にある基本的な考え方は、FooFactoryに合格するIFooParametersの二つの潜在的な実装では、種類に応じて、存在している

public interface IBar { } 
public class BarBar : IBar { } 

public class Test 
{ 
    public IBar Thing() 
    { 
     return new BarBar(); 
    } 
} 

といくつかの検証は、のインスタンスを返します- 私は、インタフェースを返すことについて心配しています。基本的なAPIはIFoo<IFooParametersのすべての実装で同じですが、1つの実装ではFooBazParametersまでの追加プロパティが必要です。

私はかなりジェネリックに新しかったので、私がしようとしていることがまったく間違っているのか、実装に何か不足しているのか分かりません。しかし、何が起こっているかについてのヘルプや説明は高く評価されます。コンパイラはあなたがIFoo<IFooParameters>Barインスタンスを変換するために許可されている場合、あなたはを渡し、その返された値にDoStuffを呼び出すことができるだろう https://dotnetfiddle.net/ZFQjCn

+1

最初のコードブロックをコンパイルするときにエラーは発生しません。あなたは適切なreproを投稿する必要があります。 –

+0

@MatthewWatsonコードをコピーして貼り付けるだけで、コードが与えられたときと同じエラーが表示されます(コンパイルすることはできません)。 – Servy

+0

@MatthewWatsonええ私はあなたが成功したビルドを得ているかどうか分かりません。私が付けた最初のフィドルでさえ、コンパイルエラーがあります。 – Kritner

答えて

3

フィドル: https://dotnetfiddle.net/wjyLS7

少しキャストで変更FooBazParametersインスタンスをパラメータとして使用しますが、BarインスタンスはFooBarParametersインスタンスしか使用できません。 Barインスタンスを無効な方法で使用できないようにする唯一の方法は、その変換が有効でないようにすることです。

+0

ああ、それは理にかなっています!私がやろうとしていることを達成する方法はありますか? (工場を落としてから、クライアントに 'IFoo <...>'が直接暗示されるようにしてください) – Kritner

+1

@Kritner異なるインターフェースの実装を別々に扱うのは決して理想的ではないので、それは意味をなさない最初にインターフェイスを持つようにしてください(またはインターフェイスのインスタンスを交換可能に扱えるようにプログラムを再設計する必要があります)。 – Servy

+0

ええ、私のルートにする必要がありますようです。少なくとも私は理解しています***なぜ***それは動作しません。ありがとう! – Kritner

関連する問題