2017-11-09 13 views
-1

IEnumerableにいくつかのデータオブジェクトがあります。データオブジェクトは様々なタイプのものがあります。それらを呼ぶことにしましょう:私はちょうどBaseData上で実行することができる方法に加えてAデータとなBData特定の機能を提供するために、ラッパークラスを作成する必要がジェネリックなファクトリメソッドジェネリック型を返す

IEnumerable<BaseData> 

BaseData can be: 
AData:BaseData 
BData:BaseData 

私はAデータと、なBDataとBaseDataの構造をミラーリング.....

AWrapper:BaseWrapper and 
BWrapper:BaseWrapper 

BaseWrapperクラスを実装することによってこの問題を解決することを決めました。 BaseWrapperを宣言

は非常に簡単です:

VAR wrappedEnumerable = EnumerableBaseData.Select(DT:しかし、どのように私は自分のライブラリの消費者がこれを書くことができるように、静的ファクトリメソッドを作成するのです

public abstract class BaseWrapper<T> where T:BaseData 
{ 
    protected T inner; 
    // Additional methods consuming "inner" as BaseData. 
} 

public class AWrapper : BaseWrapper<AData> 
{ 
     //Consuming "inner" variable here strongly typed as AData 
} 

public class BWrapper : BaseWrapper<BData> 
{ 
     //Consuming "inner" variable here strongly typed as BData 
} 

=> BaseData.Create(dt));

私はこれを行うことができると思っているだろう

public static BaseWrapper Create(BaseData inner) 
{ 
    if (inner is AData adata) 
    { 
     return new AWrapper(adata); 
    } 
    if (inner is BData bdata) 
    { 
     return new BWrapper(bdata); 
    } 
// And so on.... 
} 

しかしの戻り値の型は、メソッドを作成しますが、一般的なパラメータが求められています。 メソッドのコンシューマは、typeパラメータを指定する必要はありません。 (Tの)BaseWrapperの基本クラスである非持続的なBaseWrapperクラスは、BaseDataオブジェクトへのアクセスなしで機能を持たないため、実際には意味をなさない。

+0

することができます(あなたはもちろん、立ち往生している時点まで)コンパイル少なくとも郵便番号。たとえば、 'WrapperBase'とは​​何ですか? – DavidG

+1

「WrapperBase」タイプは突然どこから出現しましたか? 'BaseWrapper'と打つのですか? –

+0

@MatthewWatsonはい、タイプミスです。私はBaseWrapperを意味しました。 – Tormod

答えて

0

次のコードはコンパイルされます。

public class BaseData 
{ } 

public class AData : BaseData 
{ } 

public class BData : BaseData 
{ } 

public abstract class BaseWrapper 
{ 

} 
public abstract class BaseWrapper<T> : BaseWrapper where T : BaseData 
{ 
    protected T inner; 

    public BaseWrapper(T data) 
    { 
     inner = data; 
    } 

    // Additional methods consuming "inner" as BaseData. 

    public static BaseWrapper Create(BaseData inner) 
    { 
     if (inner is AData) 
     { 
      return new AWrapper((AData)inner); 
     } 
     if (inner is BData) 
     { 
      return new BWrapper((BData)inner); 
     } 
    // And so on.... 
     return null; 
    } 
} 

public class AWrapper : BaseWrapper<AData> 
{ 
    //Consuming "inner" variable here strongly typed as AData 
    public AWrapper(AData data) : base(data) 
    { 
    } 
} 

public class BWrapper : BaseWrapper<BData> 
{ 
    //Consuming "inner" variable here strongly typed as BData 
    public BWrapper(BData data) : base(data) 
    { 

    } 
} 
+0

Hm。はい、それは一般的なもののベースクラスとして非ジェネリックベースクラスを作成することについてOPの最後の段落で説明したものでした。もちろん、抽象サブクラスのメソッドをポリモーフィックに呼び出すので、強く型付けされたBaseDataにアクセスすることができます。たぶん私はジェネリックスにあまりにもハングアップしているだけで、AWrapperはBaseDataとADataプライベートフィールドの両方を持つことを受け入れるべきです。または、ADataは、その場でBaseDataをADataにダウンキャストしているプラ​​イベートゲッターにすることができます。 – Tormod

+0

正直なところ、私の答えの中にあるもののようなコードを使ってどのように役立つのか分かりません。一般的な 'BaseWrapper'を返さない限り、派生したクラスのプロパティやメソッドにアクセスできない'Create'メソッド、または結果を必要なラッパー・タイプにキャストします。 –

+0

うん。私はちょうどその問題が一般的だと思った。同等の共変型ラッパー構造を持つ第三者の構造を拡張することは、多くの人が直面するであろう何かのようです。コンパイラを満たすだけの基本クラスの必要性は、私が悪いスタートを切っていた赤い旗でした。 – Tormod

関連する問題