从WCF返回List时出现System.InvalidCastException
本文关键字:System InvalidCastException WCF 返回 List | 更新日期: 2023-09-27 18:27:53
我正在尝试为WCF应用程序实现自定义序列化程序。我在以下位置找到了有用的信息:http://pinckrow.blogspot.ru/2011/10/custom-serialization-in-wcf.html我的服务是:
[ServiceContract(Name = "testSvc")]
public interface IRemote
{
[OperationContract]
[CustomOperationBehavior]
IList<TestClass> GetAll();
[OperationContract]
[CustomOperationBehavior]
string someString();
}
public class Remote : IRemote
{
public IList<TestClass> GetAll()
{
return Program.classes;
}
public string someString()
{
return "hello!";
}
}
客户端实现:
BasicHttpBinding binding = new BasicHttpBinding(new BasicHttpSecurityMode())
{
MaxReceivedMessageSize = 65536 * 16
};
EndpointAddress epa = new EndpointAddress("http://localhost:8989/test");
testSvcClient client = new testSvcClient(binding, epa);
foreach (OperationDescription od in client.Endpoint.Contract.Operations)
{
od.Behaviors.Add(new CustomOperationBehavior());
}
var s = client.someString(); // ok!
var all = client.GetAll(); // InvalidCastException at ValidateReturnArg in mscorlib
我不理解这个问题,因为CustomMessageFormatter
中的DeserializeReply(Message message, object[] parameters)
返回有效值(TestClass实体的列表),我已经在尝试List和IList了——它同样抛出InvalidCastException。请帮忙。
添加:
[DataContract(IsReference = true)]
public class TestClass
{
[DataMember]
public TestKind Kind { set; get; }
[DataMember]
public List<TestClass> Childs { set; get; }
[DataMember]
public TestClass Parent { set; get; }
[DataMember]
public string Id { set; get; }
[DataMember]
public int Value { set; get; }
public TestClass()
{
Childs = new List<TestClass>();
}
}
[DataContract(IsReference = true)]
public class TestKind
{
[DataMember]
public int Id { set; get; }
}
程序代码:
public class Program
{
public static List<TestClass> classes;
static void Main(string[] args)
{
StartWCF();
Console.ReadKey();
MakeTestObjects();
TestWCF();
Console.ReadKey();
}
static void MakeTestObjects()
{
for (int i = 0; i < 11; i++)
{
TestKindCache.Add(new TestKind() { Id = i });
}
classes = new List<TestClass>();
Random rnd = new Random();
for (int i = 0; i < rnd.Next(5, 6); i++)
{
var parent = new TestClass()
{
Id = rnd.Next(0, 99999).ToString(),
Kind = TestKindCache.GetFromCache(rnd.Next(0, 11))
};
classes.Add(parent);
}
}
static void StartWCF()
{
new Task(() =>
{
AutoResetEvent infinity = new AutoResetEvent(false);
Uri baseAddress = new Uri("http://localhost:8989/test");
using (ServiceHost host = new ServiceHost(typeof(Remote), baseAddress))
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior
{
HttpGetEnabled = true,
MetadataExporter =
{
PolicyVersion = PolicyVersion.Default
}
};
host.Description.Behaviors.Add(smb);
host.Open();
infinity.WaitOne();
}
}).Start();
}
static void TestWCF()
{
BasicHttpBinding binding = new BasicHttpBinding(new BasicHttpSecurityMode())
{
MaxReceivedMessageSize = 65536 * 16
};
EndpointAddress epa = new EndpointAddress("http://localhost:8989/test");
testSvcClient client = new testSvcClient(binding, epa);
foreach (OperationDescription od in client.Endpoint.Contract.Operations)
{
od.Behaviors.Add(new CustomOperationBehavior());
}
var s = client.someString();
var all = client.GetAll();
client.Close();
Console.ReadKey();
}
}
堆栈跟踪:
в System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object arg, Type paramType)
в System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage msg, Object[] outArgs, Object returnValue)
в System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
в System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
в ConsoleApplication7.ServiceReference1.testSvc.GetAll()
в ConsoleApplication7.ServiceReference1.testSvcClient.GetAll() в c:'Users'ak'Documents'Visual Studio 2013'Projects'ConsoleApplication7'ConsoleApplication7'Service References'ServiceReference1'Reference.cs:строка 59
в ConsoleApplication7.Program.TestWCF() в c:'Users'ak'Documents'Visual Studio 2013'Projects'ConsoleApplication7'ConsoleApplication7'Program.cs:строка 88
в ConsoleApplication7.Program.Main(String[] args) в c:'Users'ak'Documents'Visual Studio 2013'Projects'ConsoleApplication7'ConsoleApplication7'Program.cs:строка 23
в System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
в System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
в System.Threading.ThreadHelper.ThreadStart_Context(Object state)
в System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
в System.Threading.ThreadHelper.ThreadStart()
问题是接口指定了一个IList<>
。
虽然从设计的角度来看,这是一个完全合乎逻辑的想法,也是一个很好的抽象,但如果.NET只知道它必须是一个IList<>
,那么它不知道将传入数据反序列化为什么。
将界面更改为List<>它会起作用的。
我知道,这是一个实现细节,而不是抽象,但IList<>
不起作用,List<>
起作用,因为现在.NET知道反序列化为.