gpt4 book ai didi

c# - WCF 在没有容器的情况下序列化数组或集合

转载 作者:行者123 更新时间:2023-11-30 15:04:52 26 4
gpt4 key购买 nike

我有一种情况,我们正在连接到 SOAP 服务。

我们得到的响应看起来像这样:

<SomeObject>
<item1>1</item1>
<thing1>2</thing1>
<arrayItem><foo>text</foo></arrayItem>
<arrayItem><foo>text1</foo></arrayItem>
<arrayItem><foo>text2</foo></arrayItem>
</SomeObject>

我需要复制该响应的输出。我一直遇到的问题是 <arrayItem><arrayItemList> 封装我真的需要 <arrayItemList>走开。

有谁知道我可以在我的 WCF 对象上放置什么来正确序列化/反序列化我们接收到的对象?

编辑

我正在处理的对象是这样的:

[DataContract]
public class SomeObject
{
[DataMember(Order = 0)]
public string item1 {get;set;}

[DataMember(Order = 1)]
public string thing1 {get;set;}

[DataMember(Order = 2)]
public List<arrayItem> {get;set;}
}

[DataContract]
public class arrayItem
{
[DataMember]
public string foo {get;set;}
}

最佳答案

不幸的是,我找不到很好的解决方案。但是,我确实找到了可行的解决方案。

警告 - 如果可能,您应该尝试修改 WSDL 以防止需要此解决方案。这更像是一种 hack,而不是建议的解决方案,但会在紧要关头起作用。

解决方案是实现 IClientMessageInspector 和 IEndpointBehavior。这些接口(interface)允许访问原始文本请求和响应。这些允许在将消息发送到服务或由 WCF 反序列化之前修改消息。下面是我的实现和允许对消息进行所需修改的自定义类。

public class MyService : IClientMessageInspector
{
public void DoWork()
{
// Do some stuff
}

public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
string message = reply.ToString();

// Load the reply message in DOM for easier modification
XmlDocument doc = new XmlDocument();
doc.Load(reply.GetReaderAtBodyContents());

// Perform the modification
MessageHelper.FixArrays(doc);

// Create New Message
XmlNodeReader reader = new XmlNodeReader(doc.DocumentElement);
Message newMsg = Message.CreateMessage(reply.Version, reply.Headers.Action, reader);

// Preserve the headers of the original message
if (reply.Headers.Any())
newMsg.Headers.CopyHeaderFrom(reply, 0);

foreach (string propertyKey in reply.Properties.Keys)
{
newMsg.Properties.Add(propertyKey, reply.Properties[propertyKey]);
}

// Close the original message and return new message
reply.Close();
reply = newMsg;
}

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
return null;
}
}

public static class MessageHelper
{
public static void FixArrays(XmlDocument doc)
{
// Arrearage
WrapElement(doc, "foo", "arrayItem", "http://url.com/namespace/foo");
}

private static void WrapElement(XmlDocument doc, string elementName, string wrapperName, string nameSpace)
{
var names = new XmlNamespaceManager(doc.NameTable);
names.AddNamespace("a", nameSpace);

var Nodes = doc.SelectNodes("//a:" + elementName, names);

if (Nodes.Count > 0)
{
var newBorrower = doc.CreateElement(Nodes.Item(0).Prefix, wrapperName, Nodes.Item(0).NamespaceURI);

foreach (XmlElement node in Nodes)
{
newBorrower.AppendChild(node.Clone());
}

Nodes.Item(0).ParentNode.ReplaceChild(newBorrower, Nodes.Item(0));

for (int i = 1; i <= Nodes.Count - 1; i++)
{
Nodes.Item(i).ParentNode.RemoveChild(Nodes.Item(i));
}
}
}

private static void WrapRenameElement(XmlDocument doc, string newName, string elementName, string wrapperName, string nameSpace, string newNamespace)
{
var names = new XmlNamespaceManager(doc.NameTable);
names.AddNamespace("a", nameSpace);
names.AddNamespace("b", newNamespace);

var Nodes = doc.SelectNodes("//a:" + elementName + "/..", names);

foreach (XmlElement parent in Nodes)
{
var newBorrower = doc.CreateElement(parent.Prefix, wrapperName, parent.NamespaceURI);

foreach (XmlElement child in parent.ChildNodes)
{
if (child.LocalName == elementName)
{
var newNode = RenameNode(child.Clone(), newNamespace, newName);
parent.RemoveChild(child);
newBorrower.AppendChild(newNode);
}
}

if (newBorrower.ChildNodes.Count > 0)
parent.AppendChild(newBorrower);
}
}

private static void WrapRenameElement(XmlDocument doc, string newName, string elementName, string wrapperName, string nameSpace)
{
var names = new XmlNamespaceManager(doc.NameTable);
names.AddNamespace("a", nameSpace);

var Nodes = doc.SelectNodes("//a:" + elementName + "/..", names);

foreach (XmlElement parent in Nodes)
{
var newBorrower = doc.CreateElement(parent.Prefix, wrapperName, parent.NamespaceURI);

foreach (XmlElement child in parent.ChildNodes)
{
if (child.LocalName == elementName)
{
var newNode = RenameNode(child.Clone(), nameSpace, newName);
parent.RemoveChild(child);
newBorrower.AppendChild(newNode);
}
}

if (newBorrower.ChildNodes.Count > 0)
parent.AppendChild(newBorrower);
}
}

public static XmlNode RenameNode(XmlNode node, string namespaceURI, string qualifiedName)
{
if (node.NodeType == XmlNodeType.Element)
{
XmlElement oldElement = (XmlElement)node;
XmlElement newElement =
node.OwnerDocument.CreateElement(qualifiedName, namespaceURI);

while (oldElement.HasAttributes)
{
newElement.SetAttributeNode(oldElement.RemoveAttributeNode(oldElement.Attributes[0]));
}

while (oldElement.HasChildNodes)
{
newElement.AppendChild(oldElement.FirstChild);
}

if (oldElement.ParentNode != null)
{
oldElement.ParentNode.ReplaceChild(newElement, oldElement);
}

return newElement;
}
else
{
return null;
}
}
}

就像我说的那样,它并不漂亮,本质上是一种 hack,但这个解决方案可以解决我遇到的问题。我希望没有其他人必须处理这个问题,但如果他们这样做,我希望这会有所帮助。

关于c# - WCF 在没有容器的情况下序列化数组或集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9685807/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com