2011-01-07 3 views
1

WCF-Client-Klassen sind in der Regel Setup wie:C# Einschränkung allgemeine Parameter auf einen T <T2> für Fluent Interface/Compiler kann nicht Typen schließen

public class Client : ClientBase<IService>, IService 

ich diese Kunden mit einer Erweiterung Methode erweitern möchten, die fließend ist, so dass ich eine using-Anweisung wie erklären kann: Allerdings

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

, kann ich nicht einen Weg finden, um die ursprüngliche Art des Anrufers zu halten, ohne etwas eher klobig Berufung Syntax zu erstellen:

new Client().WithCookies<Client,IService>(...) 

Ich bin mir nicht sicher, warum die Compiler nicht den T ableiten können auf dem, was ich in vergangen habe, aber es kann nicht, basierend auf der Definition der Erweiterungsmethode:

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; 
} 

ich weiß, Eric Lippert in seinem Blog, entlässt den Begriff ein von der Angabe ‚ist mir egal, was die Art Argument für die generisch ist‘ (und für allgemein gute Gründe) http://blogs.msdn.com/b/ericlippert/archive/2008/05/19/a-generic-constraint-question.aspx

eine psuedo-Implementierung wäre so etwas wie :

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; 
} 

Dies ist ein Szenario, in dem es um einen guten Sitz zu mir scheint, da ich nicht Sorgfalt tun was TChannel ist - ich bin es nicht in meinem Code verwenden würde, ich jede Client nur verwenden möchten < > als Einschränkung.

Mit diesem gesagt, kann jemand mit einer kreativen Möglichkeit kommen, meine Fluent-Anforderung ohne die Spezifikation der Typen zu implementieren?

Beachten Sie, dass Sie die in IService implementierten Servicemethoden nicht aufrufen können, wenn Sie das übergebene Originalelement nicht zurückgeben.

Antwort

1

Dies wurde in einem anderen Thread von Eric Lippert beantwortet - leider

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

Die kurze Antwort ist, Compiler-Inferenz wie das nicht funktioniert.

Weitere Details auf seinem Blog: http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx

+0

IanG hat auch einige gute Infos Hier (relativ zur Spezifikation): http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/a4847737-4a6b-4fcd-89f2-1b213aaf8422 –

-1

Der Weg zur Implementierung Ihrer Pseudo-Implementierung wäre über Reflexion. Sie können dies tun:

  1. Verwenden Reflexion an clientBase zu schauen und herauszufinden, was TChannel ist (durch die Art Hierarchie nach oben und der Suche nach ClientBase<TChannel>)
  2. Besorgen Sie sich eine spezielle Definition von WithCookiestypeof(YourClass).GetMethod("WithCookiesImpl").MakeGenericMethod(new[] { typeof(T), channelType })
  3. Invoke mit diese spezielle Definition von WithCookies

Für mich ist die Frage, warum kann nicht die Compiler die Typen in dem Aufruf von T WithCookies<T, TChannel> ableiten? Es hat die T : ClientBase<TChannel> Einschränkung auf es; Da T nur einmal von ClientBase erben kann, gibt es nur eine TChannel. (Wenn ClientBase eine Schnittstelle gewesen wäre, dann könnte es gewesen, mehr als ein TChannel.)

+0

Das ist mir in diesem Zusammenhang nicht etwas kaufen wird. Dann gibt es keine generische Einschränkung für die Methode und ich kann .WithCookies() auf Instanzen anwenden, wo es nicht hingehört. Was TChannel ist, ist für meine Bedürfnisse grundsätzlich irrelevant. Jede ClientBase <> ist akzeptabel. –

+0

Und ich stimme völlig zu, dass das Problem ist, warum der Compiler nicht schließen kann - ich bin ratlos. Wo ist Eric Lippert, wenn du ihn brauchst? –

0

keine Antwort auf die Frage, sondern etwas bewusst zu sein, wenn es Ihnen gelingt, diese Funktion zu erhalten ...

Wenn Sie verwenden die using (new Client().WithCookies(...)) Syntax und Ihre WithCookies Methode passiert, um eine Ausnahme zu werfen, dann wird die Client Instanz nicht diposed.

+0

Rechts - wie hier diskutiert btw - http://ayende.com/Blog/archive/2009/01/15/avoid-object-initializers-amp-the-using-statement.aspx –

Verwandte Themen