我正在尝试为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}}
答案 0 :(得分:0)
问题是接口指定了IList<>
。
虽然从设计的角度来看这是一个完全合乎逻辑的想法和良好的抽象,但.NET并不知道将传入数据反序列化的内容,如果只知道它必须是{{1} }。
将您的界面更改为List&lt;&gt;它会起作用。
我知道,它是一个实现细节而不是抽象,但是IList<>
不起作用而IList<>
没有,因为现在.NET知道要反序列化的内容。