2016-08-17 15 views
1

私は、オブジェクトのプロパティを設定し、そのオブジェクトを返す仮想メソッドを持つ基本サービスクラスを持っています。
次に、私は基本サービスから派生したもう1つのサービスを持ち、基本メソッドをオーバーライドします。オーバーライドされたメソッドでは、派生サービスは共通プロパティを設定するためにbase.DowWork()を実行し、追加のプロパティも設定します。
記事herehereに基づいて、私はジェネリックスを使ってこれを行うことができました。
汎用インスタンスを返すファクトリメソッド

public interface IResult 
    { 
    } 

    public class BaseResult : IResult 
    { 
     public string CommonProperties { get; set; } 
    } 

    public class AdditionalResult : BaseResult 
    { 
     public string AdditionalProperties { get; set; } 
    } 

    public interface IService<T> where T : IResult 
    { 
     T DoWork(); 
    } 

    public class BaseService<T> : IService<T> where T : BaseResult, new() 
    { 
     public virtual T DoWork() 
     { 
      var t = new T(); 

      t.CommonProperties = "Some Value"; 

      return t; 
     } 
    } 
    public class AdditionalService : BaseService<AdditionalResult> 
    { 
     public override AdditionalResult DoWork() 
     { 
      var addtionalResult = base.DoWork(); 

      addtionalResult.CommonProperties = "Override value that was set by BaseService"; 
      addtionalResult.AdditionalProperties = "Set additional properties"; 

      return addtionalResult; 
     } 
    } 

これまでのところは良い今、私はいくつかの種類に基づいて、サービスのインスタンスを返します。ファクトリメソッドを作成したいです。アプリケーションは、私がの署名がどうあるべきかを把握することはできませんよしかし

以下
class Program 
    { 
     static void Main() 
     { 
      var factory = new MyFactory(); 
      var service = factory.GetService(0); 
      var iresult = service.DoWork(); 

      // do something here with IResult    
     } 
    } 

以下のようなファクトリメソッド

public class MyFactory 
{ 
    public IService<IResult> GetService(int someType) 
    { 
     if (someType == 0) 
     { 
      return (IService<IResult>)new BaseService<BaseResult>(); 
     } 

     if (someType == 1) 
     { 
      return (IService<IResult>)new AdditionalService(); 
     } 

     // note I may have more types and services here. But for simplicity i am using only 2 

     throw new NotSupportedException(); 
    } 
} 

ある)サービスインスタンスを取得し、(DoWorkを呼び出すために工場を使用しますこのファクトリメソッドは?提案に基づきhere私はサービスインスタンスをキャストしていますが、アプリケーションを実行しながら、私は実行時例外を取得しています

タイプ のオブジェクトをキャストできません「BaseService 1 [BaseResult]」へ タイプ「IService 1 [IResult]」私は工場でサービスインスタンスをキャストしていない場合

はその後、私は時間のコンパイルエラー取得

暗黙的 に型「BaseService」を変換できません。 'IService'。明示的な変換が存在します( キャストがありません)

答えて

2

SOの質問Understanding Covariant and Contravariant interfaces in C#を参照してください。

共分散(outキーワード)を使用します。 IServiceインターフェイスジェネリック型に追加すると、期待どおりに動作します。私が知っている

public interface IService<out T> where T : IResult 

SOのリンクを投稿しないことを好むが、私はおそらくanswered in that questionすでに以上またはより良い何かを書き込むことはできません。

+0

上記で提供したリンクのうちの1つ「http:// stackoverflow.com/questions/1723648/how-to-inherit-method-but-different-return-type」は、戻り型共分散と呼ばれます。これはC#ではサポートされていません。 – LP13

+0

@ LP13 - リンクされた例では、共通の型が返されないため、動作しません。この場合、戻り値の型は 'IResult'を実装する必要があります。これはOKです.IIServiceを実装するすべての型は、IResultを実装する型を返すメンバを持つ必要があります。 – Igor

+0

ありがとうございました。返信をお詫び申し上げます – LP13

関連する問題