WCF client classes are typically setup like:
public class Client : ClientBase<IService>, IService
I want to extend these clients with an extension method that is Fluent, so that I can declare a using statement like:
using (new Client().WithCookies(...)) {}
However, I can't figure out a way to maintain the original Type of the caller, without creating some rather clunky calling syntax:
new Client().WithCookies<Client,IService>(...)
I'm not sure why the compiler can't infer the T based on what I've passed in, but it can't, based on the definition of the extension method:
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;
}
I know Eric Lippert in his blog, dismisses the notion of specifying a 'I don't care what the type argument to the generic is' (and for generally good reasons) http://blogs.msdn.com/b/ericlippert/archive/2008/05/19/a-generic-constraint-question.aspx
A psuedo-implementation would be something like:
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;
}
This is one scenario where it seems to me a good fit, as I don't care what TChannel is -- I'm not going to use it in my code, I just want to use any ClientBase<> as a constraint.
With that said, can anyone come up with a creative way to implement my Fluent requirement without the specification of the Types?
Keep in mind that if you don't return the original item passed in, you lose the ability to call service methods implemented in IService.