带有动态参数的ChannelFactory错误

时间:2013-03-13 02:44:01

标签: .net wcf c#-4.0 wcf-client channelfactory

此问题与Bug in the dynamic language runtime in combination with IIS 7.5

有关 如果我为其提供正确类型的动态对象,

ChannelFactory会挂起。

dynamic src = "MSFT";

var binding = new BasicHttpBinding();
var endpoint = new EndpointAddress("http://www.restfulwebservices.net/wcf/StockQuoteService.svc");
var channel = new ChannelFactory<IStockQuoteService>(binding, endpoint).CreateChannel();

// this will print just fine
Console.WriteLine(channel.GetStockQuote(src as string));

// this will print just fine
Console.WriteLine(new StockQuoteServiceClient().GetStockQuote(src));

// this will never print and the application will hang with no exceptions
Console.WriteLine(channel.GetStockQuote(src));
  • 上面的服务是公开的,不是我的,如果您只是将服务引用添加到代码中提供的端点,您可以自己测试此代码;
  • StockQuoteServiceClient由“添加服务引用”菜单项创建,并使动态对象正常;
  • 当我在Debug上使用F5启动应用程序,打印所有行并且程序正确退出时,这种情况并不会发生;
  • 如果我运行它然后在执行期间附加调试器,我可以看到它挂在channel.GetStockQuote(src)的调用上;
  • 如果我离开它,该程序会占用我所有的记忆;
  • 只有在我使用自己的ChannelFactory动态对象时才会挂起,如评论中所述。

当“添加服务引用”创建的动态对象运行得很好时,为什么我的ChannelFactory在将动态对象作为参数时挂起?

1 个答案:

答案 0 :(得分:3)

当您使用dynamic关键字时,与动态变量相关的每个代码都将由DLR在运行时编译。当您使用动态变量调用方法时,实际方法签名在编译时是未知的,并且方法返回类型以及与其相关的所有内容创建Eric Lippert称为"Dynamic Contagion"的内容:

  

“正如我上次指出的那样,当一个电话的参数是动态的时候   那么编译器会对结果进行分类的几率非常高   呼叫也是动态的;污点蔓延。事实上,当你   在动态表达式上使用几乎所有运算符,结果是   动态类型,但有一些例外。 (“是”例如总是返回   一个bool。)你可以“治愈”一个表达,以防止它蔓延   通过将其投射到对象或任何其他非动态的动态主义   你想要的类型;将动态转换为对象是一种身份转换。“

WCF内部使用了大量的接口和抽象,并且有关于抽象和接口的known DLR limitation,其中DLR无法解析正确的类型。 (另请查看this SO discussion

我能够使用反射正确调用ChannelFactory并将参数转换为其他类型(并且还尝试使用错误的类型调用服务)。问题必须与DLR有关。

我无法调试DLR编译,但问题可能与“动态传染”和界面解决错误有关。使用“传染”WCF调用的每个部分都可以在运行时编译,类型解析错误可能会在某些极端情况下创建一些endles循环,如调用基本方法的覆盖方法实现,并且基类被错误地解析为同一个子类类。

一些WCF内部在附加调试器(Debugger.IsAttached)时执行额外的指令,这通常包括断言,检查和归属。额外的指令可能提供一些杀死“动态传染”的信息,并避免虚假的无限循环。