WCF: исключение StackoverFlow
Я получаю исключение при попытке обслуживать класс.NET ServiceController. It serializes fine when it's null but once I populate it I get a stackru exception.
Так что это работает:
[DataMember]
public ServiceController MyServiceController
{
get { return null; }
}
Но это выдает ошибку "Необработанное исключение типа" System.StackruException "произошло в System.ServiceProcess.dll":
public class TestClass
{
private ServiceController _serviceController;
[DataMember]
public ServiceController MyServiceController
{
get { return ServiceController.GetServices()[0];
}
}
Странно то, что в логах вообще нет ошибок. Когда есть ошибка, я вижу ее в журналах, так что это не потому, что мои журналы не работают. Вот мой конфигурационный файл
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyCompany.Wcf.RdbmsServer.RdbmsServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyCompany.Wcf.RdbmsServer.RdbmsServiceBehavior"
name="MyCompany.Wcf.RdbmsServer.RdbmsService">
<endpoint address="" binding="wsHttpBinding" contract="MyCompany.Wcf.RdbmsServer.IRdbmsService" bindingConfiguration="IncreaseMaxMessageSize">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/MyCompany.Wcf.RdbmsServer/RdbmsService/" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="IncreaseMaxMessageSize"
maxReceivedMessageSize="655360000">
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="All"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
Вот мой сервисный интерфейс
[ServiceContract]
public interface IRdbmsService
{
[OperationContract]
TestClass GetServiceControllerList();
}
И реализация:
public TestClass GetServiceControllerList()
{
return new TestClass();
}
Есть идеи?
2 ответа
Вы вызываете сериализатор для рекурсии:
public class TestClass
{
private ServiceController _serviceController;
[DataMember]
public ServiceController MyServiceController
{
get { return ServiceController.GetServices()[0]; // <-- this returns your service
}
}
Служба, которую он возвращает, является вашей IRdbmsService
, который возвращает TestClass
, Затем необходимо сериализовать и т. Д.
Изменить: чтобы уточнить:
Когда TestClass сериализуется, сериализатор просматривает все свои DataMember
свойства, одним из которых является ServiceController
, Затем он сериализует это свойство, которое делает это на get
:
return ServiceController.GetServices()[0];
поскольку IRdbmsService
является единственной службой, определенной в вашей области, она имеет индекс 0 из ответа GetServices
вызов, поэтому он должен быть сериализован. С возвращаемым типом GetServiceControllerList
является TestClass
, TestClass
затем должен быть сериализован, что возвращает нас к началу (отсюда и рекурсия).
То, как решить эту проблему, зависит от того, что вы пытаетесь сделать. В данный момент этот сервис возвращает информацию о себе вызывающей стороне, что для меня не имеет смысла; звонящий уже имеет эту информацию во время потребления (до совершения звонка). Можете ли вы уточнить свои намерения?
Да, в конструкторе ServiceController CLASS вы, вероятно, вызываете что-то рекурсивное, у которого нет условия остановки, поэтому каждый раз, когда оно вызывает что-то рекурсивное, программа переносится в стек, и, как я уже говорил, условия остановки нет, он будет добавляться в стек до тех пор, пока память не взорвется, поэтому ему присваивается имя ошибки StackOverFlow.
Предложение: Добавьте точку останова для отладки там, где ее вызов рекурсивен. Это так легко при отладке.