C# __WCFService的类型和继承
当我使用Postman chrome发送请求时,如果我不将_类型添加为“_类型”:“BusTextMessage:#TransportModels.Messages”对象将无法正确序列化,因为它不知道如何实例化BusMessage类。我已经定义了Type属性,它定义了消息的类型。是否有可能重写类型行为,例如根据类型属性返回正确的实现?我不希望任何人手动将_类型信息放入json,那么在反序列化之前是否可以编辑json,如果不存在,是否可以手动将_类型属性添加到json?例如,我想做这样的事情:C# __WCFService的类型和继承,c#,json,wcf,C#,Json,Wcf,当我使用Postman chrome发送请求时,如果我不将_类型添加为“_类型”:“BusTextMessage:#TransportModels.Messages”对象将无法正确序列化,因为它不知道如何实例化BusMessage类。我已经定义了Type属性,它定义了消息的类型。是否有可能重写类型行为,例如根据类型属性返回正确的实现?我不希望任何人手动将_类型信息放入json,那么在反序列化之前是否可以编辑json,如果不存在,是否可以手动将_类型属性添加到json?例如,我想做这样的事情:
[DataContract]
public abstract class BusMessage
{
[DataMember(Name = "encoding")]
public string Encoding { get; set; }
[DataMember(Name = "type")]
public virtual MessageType Type
{
get { return _type; }
private set { _type = value; }
}
}
[DataContract]
public class BusTextMessage : BusMessage
{
[DataMember(Name = "type")]
public override MessageType Type
{
get { return MessageType.Text; }
}
[DataMember(Name = "payload")]
public string Payload { get; set; }
}
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
public interface ICommunicationService
{
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/SendMessage")]
string SendMessage(BusMessage jsonMessage);
}
}
我找到了这种方法,但似乎不可用:
public void BeforeDeserialization(string json)
{
if(json doesnt include __type)
{
if(json property type(my property) is MessageType.Text)
add to json "__type":"BusTextMessage:#TransportModels.Messages"
///etc
}
}
我认为您需要将KnownType属性添加到BusMessage类中
[OnDeserializing()]
internal void OnDeserializingMethod(StreamingContext context)
{
}
这是我发现的最快的解决方案。我配置MessageInspector并处理AfterReceiveRequest。然后检查消息格式(XML、JSON)。如果它是XML(例如,从任何用C#编写的WCF客户端发送,WCF配置为使用XML发送所有内容),那么我接受该消息,因为WCF机制将自动插入字段类型。否则,我会检查它是否是JSON,例如从外部客户端发送的JSON。如果它不包含属性“\uuuuu type”,我将检查我的属性类型并生成适当的\uuuu类型值。例如,如果我的类型等于Text,我将添加uu Type属性BusTextMessage:#TransportModels.Messages并将其插入JSON,然后重新创建消息。我找不到更快更简单的解决方案,它似乎正在发挥作用。处理我在找到的收件人后的请求
公共类MessageTypeInspector:IDispatchMessageInspector
{
接收请求后的公共对象(ref消息请求、IClientChannel通道、InstanceContext InstanceContext)
{
重新创建消息(ref请求);
返回null;
}
}
私有void重新创建消息(参考消息消息消息)
{
WebContentFormat messageFormat=此.GetMessageContentFormat(消息);
var ms=新内存流();
XmlDictionaryWriter writer=null;
开关(消息格式)
{
案例WebContentFormat。默认值:
案例WebContentFormat.Xml:
writer=XmlDictionaryWriter.CreateTextWriter(毫秒);
打破
案例WebContentFormat.Json:
writer=JsonReaderWriterFactory.CreateJsonWriter(ms);
打破
案例WebContentFormat.Raw:
此.ReadRawBody(ref消息);
打破
}
message.WriteMessage(编写器);
writer.Flush();
string messageBody=Encoding.UTF8.GetString(ms.ToArray());
if(messageFormat==WebContentFormat.Json&&!messageBody.Contains(“\uu类型”))
messageBody=AddTypeField(messageBody);
ms.Position=0;
ms=newmemoryStream(Encoding.UTF8.GetBytes(messageBody));
XmlDictionaryReader=messageFormat==WebContentFormat.Json?
JsonReaderWriterFactory.CreateJsonReader(ms,XmlDictionaryReaderQuotas.Max):
CreateTextReader(ms,xmldirectionaryReaderquotas.Max);
Message newMessage=Message.CreateMessage(reader,int.MaxValue,Message.Version);
newMessage.Properties.CopyProperties(message.Properties);
消息=新消息;
}
私有WebContentFormat GetMessageContentFormat(消息消息)
{
WebContentFormat=WebContentFormat.Default;
if(message.Properties.ContainsKey(WebBodyFormatMessageProperty.Name))
{
WebBodyFormatMessageProperty bodyFormat;
bodyFormat=(WebBodyFormatMessageProperty)message.Properties[WebBodyFormatMessageProperty.Name];
format=bodyFormat.format;
}
返回格式;
}
私有字符串AddTypeField(字符串jsonReply)
{
var typeRegex=newregex(“\”type\”:(?[0-9]*)”;
Match Match=typeRegex.Match(jsonReply);
如果(匹配成功)
{
int number=Int32.Parse(match.Groups[“number”].Value);
变量类型=(消息类型)编号;
var nameFormat=string.Format(“总线{0}消息”,类型);
string format=string.format(“\”\uu type\”:\“{0}:\35; TransportModels.Messages\”,nameFormat);
jsonReply=“{”+string.Format(“{0},{1}”,Format,jsonReply.Substring(1));
返回jsonReply;
}
其他的
{
抛出新异常(“错误的消息类型”);
}
}
这不是我问题的答案。此外,在WCFService中添加它就足够了
[DataContract]
[KnownType(typeof(BusTextMessage)]
public class BusMessage
{
.
.
.
}
public class MessageTypeInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
RecreateMessage(ref request);
return null;
}
}
private void RecreateMessage(ref Message message)
{
WebContentFormat messageFormat = this.GetMessageContentFormat(message);
var ms = new MemoryStream();
XmlDictionaryWriter writer = null;
switch (messageFormat)
{
case WebContentFormat.Default:
case WebContentFormat.Xml:
writer = XmlDictionaryWriter.CreateTextWriter(ms);
break;
case WebContentFormat.Json:
writer = JsonReaderWriterFactory.CreateJsonWriter(ms);
break;
case WebContentFormat.Raw:
this.ReadRawBody(ref message);
break;
}
message.WriteMessage(writer);
writer.Flush();
string messageBody = Encoding.UTF8.GetString(ms.ToArray());
if (messageFormat == WebContentFormat.Json && !messageBody.Contains("__type"))
messageBody = AddTypeField(messageBody);
ms.Position = 0;
ms = new MemoryStream(Encoding.UTF8.GetBytes(messageBody));
XmlDictionaryReader reader = messageFormat == WebContentFormat.Json ?
JsonReaderWriterFactory.CreateJsonReader(ms, XmlDictionaryReaderQuotas.Max) :
XmlDictionaryReader.CreateTextReader(ms, XmlDictionaryReaderQuotas.Max);
Message newMessage = Message.CreateMessage(reader, int.MaxValue, message.Version);
newMessage.Properties.CopyProperties(message.Properties);
message = newMessage;
}
private WebContentFormat GetMessageContentFormat(Message message)
{
WebContentFormat format = WebContentFormat.Default;
if (message.Properties.ContainsKey(WebBodyFormatMessageProperty.Name))
{
WebBodyFormatMessageProperty bodyFormat;
bodyFormat = (WebBodyFormatMessageProperty)message.Properties[WebBodyFormatMessageProperty.Name];
format = bodyFormat.Format;
}
return format;
}
private string AddTypeField(string jsonReply)
{
var typeRegex = new Regex("\"type\":(?<number>[0-9]*)");
Match match = typeRegex.Match(jsonReply);
if (match.Success)
{
int number = Int32.Parse(match.Groups["number"].Value);
var type = (MessageType)number;
var nameFormat = string.Format("Bus{0}Message", type);
string format = string.Format("\"__type\":\"{0}:#TransportModels.Messages\"", nameFormat);
jsonReply = "{" + string.Format("{0},{1}", format, jsonReply.Substring(1));
return jsonReply;
}
else
{
throw new Exception("Wrong message type.");
}
}