此问题与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
由“添加服务引用”菜单项创建,并使动态对象正常; channel.GetStockQuote(src)
的调用上; ChannelFactory
动态对象时才会挂起,如评论中所述。当“添加服务引用”创建的动态对象运行得很好时,为什么我的ChannelFactory
在将动态对象作为参数时挂起?
答案 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)时执行额外的指令,这通常包括断言,检查和归属。额外的指令可能提供一些杀死“动态传染”的信息,并避免虚假的无限循环。