2011-01-07 64 views
1

WCF客户端类典型​​地是设置这样的:C#约束通用参数用于流利的接口为T <T2> /编译器不能推断类型

public class Client : ClientBase<IService>, IService 

我想这些客户端与是良好的扩展方法扩展,这样我可以声明using语句,如:

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

但是,我不能想出一个办法来维持呼叫者的原始类型,而不产生一些非常笨拙调用语法:

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

这是我认为合适的一种情况,因为我不知道护理 TChannel是什么 - 我不打算在我的代码中使用它,我只想使用任何ClientBase < >作为约束。这样说,任何人都可以想出一个创造性的方式来实现我的Fluent需求,而不需要指定类型?

请记住,如果您没有返回传入的原始项目,您将失去调用在IService中实现的服务方法的能力。

回答

-1

实现伪执行的方式将通过反射。你可以这样做:

  1. 使用反射来看看clientBase和制定出什么TChannel是(由一个上升的类型层次,寻找ClientBase<TChannel>
  2. 使用typeof(YourClass).GetMethod("WithCookiesImpl").MakeGenericMethod(new[] { typeof(T), channelType })获得WithCookies专门定义
  3. 调用这个专门的定义WithCookies

对我来说,问题是,为什么编译器不能推断到T WithCookies<T, TChannel>的调用类型?它对它有约束条件;由于T只能从ClientBase继承一次,因此只能有一个TChannel。 (如果ClientBase一直是个接口,那么有可能已经超过一个TChannel。)

+0

这不会给我买在这种情况下任何东西。然后对方法没有通用约束,我可以将.WithCookies()应用于不属于它的实例。 TChannel基本上与我的需求无关。任何ClientBase <>都可以接受。 – 2011-01-07 19:48:33

+0

我完全同意这个问题,为什么编译器无法推断 - 我很茫然。 Eric Lippert在你需要他的时候在哪里? – 2011-01-07 19:49:28

0

不是一个问题的答案,而是一个需要注意,如果你设法得到这个工作的......

如果您使用using (new Client().WithCookies(...))语法,并且您的WithCookies方法恰巧会抛出异常,那么Client实例将不会显示。

+0

正确 - 正如此处讨论btw - http://anende.com/Blog/archive/2009/01/15/avoid-object-initializers-amp-the-using-statement.aspx – 2011-01-07 19:44:24

相关问题