从WCF返回List时System.InvalidCastException

时间:2014-10-27 08:37:12

标签: c# wcf

我正在尝试为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

我不明白问题因为DeserializeReply(Message message, object[] parameters) CustomMessageFormatter中的[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; } } 返回有效值(TestClass实体列表),我已经尝试过List和IList - 它同样会抛出InvalidCastException。请帮助。

加入:

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

堆栈跟踪:

{{1}}

1 个答案:

答案 0 :(得分:0)

问题是接口指定了IList<>

虽然从设计的角度来看这是一个完全合乎逻辑的想法和良好的抽象,但.NET并不知道将传入数据反序列化的内容,如果只知道它必须是{{1} }。

将您的界面更改为List&lt;&gt;它会起作用。

我知道,它是一个实现细节而不是抽象,但是IList<>不起作用而IList<>没有,因为现在.NET知道要反序列化的内容。