2011-01-07 7 views
1

WCFクライアントクラスは、通常のように設定されているタイプの推論することはできません。C#の制約ジェネリックパラメータは

public class Client : ClientBase<IService>, IService 

を私は流暢である拡張メソッドでこれらのクライアントを拡張したいです、しかし、私はいくつかのかなり不格好な呼び出し構文を作成せずに、呼び出し側の元の型を維持するための方法を把握することはできません

using (new Client().WithCookies(...)) {} 

私のようなusingステートメントを宣言することができるように
new Client().WithCookies<Client,IService>(...) 

私は拡張メソッドの定義に基づいて、なぜコンパイラは、私が渡されたものに基づいてTを推測することはできませんが、それができないかわからない:

public static T WithCookies<T, TChannel>(this T clientBase, IEnumerable<Cookie> cookies) 
    where T : ClientBase<TChannel>, TChannel 
    where TChannel : class 
{ 
    HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(); 
    requestProperty.Headers.Add(HttpCookieHeader, string.Join("; ", cookies.Select(c => c.ToCookieString(false)))); 

    new OperationContext(clientBase.InnerChannel).OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty; 
    return clientBase; 
} 

私は彼のブログでエリックリペットを知って、指定の概念を閉じる http://blogs.msdn.com/b/ericlippert/archive/2008/05/19/a-generic-constraint-question.aspx

擬似実装はようなものになるだろう(と一般的に正当な理由のために)「私は、ジェネリックの型引数が何であるかを気にしません」 :

public static T WithCookies<T>(this T clientBase, IEnumerable<Cookie> cookies) 
    where T : ClientBase<> 
{ 
    HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(); 
    requestProperty.Headers.Add(HttpCookieHeader, string.Join("; ", cookies.Select(c => c.ToCookieString(false)))); 

    new OperationContext(clientBase.InnerChannel).OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty; 
    return clientBase; 
} 

これは私にはうまくいかないようなシナリオの1つですケア TChannelは何ですか - 自分のコードで使用するつもりはありません、私はちょうどClientBaseを使用したいです< >を制約として使用します。

これで、タイプの仕様がなくても私のFluent要件を実装する創造的な方法を考え出すことができますか?

渡された元のアイテムを返さないと、IServiceで実装されているサービスメソッドを呼び出すことができなくなります。

答えて

1

これはエリックリペットで別のスレッドに答えた -

Generic extension method : Type argument cannot be inferred from the usage

短い答えは、コンパイラの推論が、残念ながらそのように動作しません、です。彼のブログ上

詳細: http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx

+0

IanGには良い情報がありますここ(仕様に関連):http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/a4847737-4a6b-4fcd-89f2-1b213aaf8422 –

-1

擬似実装を実装する方法は、リフレクションによるものです。

  1. 使用反射clientBaseを見て、(型階層を上がっていくとClientBase<TChannel>を探すことにより)TChannelが何であるかを動作するように
  2. typeof(YourClass).GetMethod("WithCookiesImpl").MakeGenericMethod(new[] { typeof(T), channelType })
  3. 呼び出しを使用してWithCookiesの特別な定義を取得します。あなたはこれを行うことができます質問がある私にとってWithCookies

のこの特別な定義は、なぜコンパイラはT WithCookies<T, TChannel>への呼び出しでタイプを推測することはできませんか?それにはT : ClientBase<TChannel>という制約があります。 TはClientBaseから一度しか継承できないため、TChannelの1つしか存在できません。 (ClientBaseがインタフェースされていた場合は、複数のTChannelがあったかもしれない。)

+0

この文脈で私に何かを購入することはありません。その後、メソッドには一般的な制約はなく、私はそれが属していないインスタンスに.WithCookies()を適用できます。 TChannelは基本的に私のニーズに無関係です。どんなClientBase <>でもかまいません。 –

+0

そして、コンパイラが推論することができない理由が問題になっていることに私は完全に同意します - 私は迷っています。あなたが彼を必要とするとき、エリック・リッパートはどこですか? –

0

ない質問への答えが、あなたは、この作業を取得するために管理する場合の注意すべき何か...

の場合using (new Client().WithCookies(...))構文を使用し、WithCookiesメソッドが例外をスローした場合、ClientインスタンスはDIPされません。

+0

右 - ここで議論されているようにbtw - http://ayende.com/Blog/archive/2009/01/15/avoid-object-initializers-amp-the-using-statement.aspx –

関連する問題