带有动态参数的ChannelFactory错误

Jul*_*ano 8 .net wcf wcf-client channelfactory c#-4.0

此问题与动态语言运行时中的Bug以及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));
Run Code Online (Sandbox Code Playgroud)
  • 上面的服务是公共的,不是我的,如果您只是将服务引用添加到代码中提供的端点,您可以自己测试此代码;
  • StockQuoteServiceClient 是由Add Service Reference菜单项创建的,并且使动态对象很好;
  • 当我在Debug上使用F5启动应用程序时,这种神奇不会发生,所有行打印并且程序正确退出;
  • 如果我运行它然后在执行期间附加调试器,我可以看到它挂在调用上channel.GetStockQuote(src);
  • 如果我离开它,程序会占用我所有的记忆;
  • 它只会在我使用自己ChannelFactory的动态对象时挂起,如注释中所述.

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

lst*_*ern 3

当您使用dynamic关键字时,与动态变量相关的每个代码都将由DLR在运行时进行编译。当您使用动态变量调用方法时,实际的方法签名在编译时是未知的,方法返回类型以及与之相关的所有内容都未知,从而创建了 Eric Lippert 所谓的“动态传染”

“正如我上次指出的,当调用的参数是动态的时,编译器也很有可能将调用的结果分类为动态;污点会传播。事实上,当您在动态表达式,结果是动态类型,但有一些例外。(例如,“is”总是返回 bool。)您可以通过将表达式强制转换为对象或任何其他对象来“修复”表达式以防止其传播动态性您想要的非动态类型;将动态转换为对象是身份转换。”

WCF 内部使用大量接口和抽象,并且存在有关抽象和接口的已知 DLR 限制,其中 DLR 无法解析正确的类型。(另请参阅此 SO 讨论

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

我无法调试 DLR 编译,但问题可能与“动态传染”和接口解析错误有关。通过“传染”,WCF 调用的每个部分都可以在运行时进行编译,并且类型解析错误可能会在某些极端情况下创建一些无限循环,例如调用基方法的重写方法实现,并且基类被错误地解析为同一个子类班级。

当附加调试器 ( Debugger.IsAttached ) 时,某些 WCF 内部会执行额外的指令,这些指令通常包含断言、检查和归因。额外的指令可以提供一些信息来消除“动态传染”并避免虚假的无限循环。