2016-08-17 8 views
1

ときに実装をこれは私がそれを使用する方法をされて戻りますGetFooStuff(id)を使ってfooStuffを取得します。C#のジェネリックメソッドの型がインターフェイス

public interface IFoo() : IBar 
{ 
    FooStuff GetFooStuff(int id); 
} 

public class Foo 
{ 
    public FooStuff GetFooStuff(int id) 
    { 
     // get fooStuff 
     return fooStuff; 
    }  
} 

public interface IBar 
{ 
     T DoBarStuff<T>(); 
} 

public class Bar 
{ 
    public T DoBarStuff<T>() 
    { 
     // do bar stuff 
     return T; 
    } 
} 

Tは任意のインターフェイスであり、 'return T;'実行された実装が必要です。今のように、私はTの下でこのエラーを 'return T;ライン。

Tは、指定されたコンテキストでは無効な型です。この時点でタイプパラメータ の名前は無効です。

ありがとうございます!

+0

ヒントを使用:あなたはTのインスタンスを返す必要があり、ないタイプのT自体を... – ViRuSTriNiTy

+2

'T 'は型です。 'return T;'は 'return int;'と似ています。返す* what * int?あなたのメソッドが 'T'型のオブジェクトを作成した場合は、それを返します。何かを返すつもりがない場合は、定義に戻り値を使用せず、 'void'を使用してください。 –

+0

これを見てください:http://stackoverflow.com/questions/731452/create-instance-of-generic-type#answer-731637 – Corporalis

答えて

2

これは動作するはずです:

public interface IBar 
{ 
    T DoBarStuff<T>() where T : class, new(); 
} 

public class Bar : IBar 
{ 
    public T DoBarStuff<T>() where T : class, new() 
    { 
     // do bar stuff 
     return new T(); 
    } 
} 

しかし、あなたは方法DoBarStuffを使用するときに型を指定する必要があります:

用途:var fooStuff = _foo.DoBarStuff<FooWhatEver>().GetFooStuff(id)


あなたはそうではない場合あなたのクラス/インターフェースジェネリックを作りたいと思っています:

public interface IBar<T> where T : class, new() 
{ 
    T DoBarStuff<T>(); 
} 

public class Bar<T> : IBar<T> where T : class, new() 
{ 
    public T DoBarStuff() 
    { 
     // do bar stuff 
     return new T(); 
    } 
} 

用途:

IBar bar = new Bar<FooWhatEver>(); 
var fooStuff = _foo.DoBarStuff().GetFooStuff(id); 

しかし、このすべては、インタフェースのための(デフォルトのコンストラクタを持つ)のみインスタンス化クラスは動作しません。

インターフェイスの場合は、インターフェイスとその実装の間で変換する必要があります。

簡単な方法は、辞書を使うことです(テスト目的のために、@ N_tro_Pを提案するように依存関係注入フレームワークを使用することができます。

あなたは(あなたの継承とジェネリック一部を忘れてはいけない)このようなものに終わるだろう:

public class Bar // <T> or not depending on your choice 
// You can add this constraint to avoid value types (as int): 
// where T : class 
{ 
    Dictionary<Type, Type> _container = new Dictionary<Type, Type>(); 
    { 
     {typeof(IFoo), typeof(Foo)} 
    }; 

    public T DoBarStuff() // <T> or not depending on your choice 
    // You can add this constraint to avoid value types (as int): 
    // where T : class 
    { 
     // get fooStuff 

     return Activator.CreateInstance(_container[typeof(T)]); 
     // You will get an error if T is not in the container 
     // or if _container[typeof(T)] is not instantiable 
     // or doesn't have a default constructor. 
    } 
} 

唯一の問題は、すべてのあなたのインターフェイスで辞書/容器を満たす必要があります/クラスを使用したい場合、それはかなり面倒な扱いになることがあります。 私の最初の解決方法の1つを好む方がいいでしょう。

+0

TをIFooだけでなく、どんなインターフェースにしたいのですか? – User123

+0

私の悪い、ちょうど拘束のIFooを削除 –

+0

あなたは文字通り私が言い返したことをコピーするあなたの投稿を編集しましたか?以前はこれはできないと言っていましたが、今では私が書いたものを突然書き直すことができます。泥棒 –

0

これは可能ですが、発信シグネチャの書き方はできません。

あなたのバーはIBarとFooを使用せず、インターフェイスとして使用しています。だからに変更する必要があります。インターフェイスとやりとりする方法を混乱させるかもしれません。

調整コード

public interface IFoo 
{ 
    FooStuff GetFooStuff(int id); 
} 

public class Foo : IFoo 
{ 
    public FooStuff GetFooStuff(int id) 
    { 
     // get fooStuff 
     return fooStuff; 
    }  
} 

public interface IBar 
{ 
     T DoBarStuff<T>(); 
} 

public class Bar : IBar 
{ 
    public T DoBarStuff<T>() 
    { 
     // do bar stuff 
     return container[typeof(T)]; 
    } 
} 

あなたが求めているものの使用は、あなたがこのような場合、タイプを置くようにすることです。

var fooStuff = _foo.DoBarStuff<BarStuff>().GetFooStuff(id); 

これは依存性コンテナの動作方法です。それらは、型をキーとしてインスタンス化されたオブジェクトを辞書に格納します。すなわち 辞書インスタンス。

また、他の場所に格納されている工場もあるかもしれませんが、それはあなたの署名が一致する必要があるか、または依存関係に独立してアクセスしていると仮定しているので、 Dictionary> factories;

一般的に、私は依存性コンテナを見ていきます。あなたが取り組んでいるものは、単純にそれを模様と呼んでいるかもしれません。すでに多くのものが作られているので、あなた自身を回す必要はありません。オブジェクトを型で返す場合は、それが依存関係コンテナです。 また、コンテナに結合されないように注入することをお勧めします。言い換えれば、インターフェースでラップして、既製品1(ユニティなど、MEF)

public interface IDependencyContainer 
{ 
    T Resolve<T>(); 
    void Register<T>(T instance); 
    void Register<T>(Func<T> instance); 
} 
+0

おそらくあなたは答えからOPのコードを削除する必要があります、それは冗長です(そしてコンパイルされません)。答えの2番目の部分は役に立ちます。 – Groo

+0

彼のコードは間違っていて、修正しました。 –

+0

私はまだ 'return T;'を見ています。これはOPがコンパイルエラーを取得していたところです。これは[その他の回答](http://stackoverflow.com/a/38998949/69809)で修正された部分です。 – Groo

関連する問題