从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()

从WCF返回List时出现System.InvalidCastException

问题是接口指定了一个IList<>

虽然从设计的角度来看,这是一个完全合乎逻辑的想法,也是一个很好的抽象,但如果.NET只知道它必须是一个IList<>,那么它不知道将传入数据反序列化为什么。

将界面更改为List<>它会起作用的。

我知道,这是一个实现细节,而不是抽象,但IList<>不起作用,List<>起作用,因为现在.NET知道反序列化为.