123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- using System;
- using System.Linq;
- using System.Text;
- using Vinno.IUS.Common.IO;
- using Vinno.IUS.Common.Utilities;
- namespace Vinno.IUS.Common.Network.Transfer
- {
- public class Message : IDisposable
- {
- private const int MessageBuffers = 2;
- private const int TagBuffers = 2;
- private const int ElementBuffers = 2;
- public bool IsDisposed { get; private set; }
- public string CreateId { get; }
- public MessageTag Tag { get; private set; }
- public IElement Element { get; private set; }
- public Message(MessageTag tag, IElement element) : this()
- {
- if (tag.TransferType != element.TransferType)
- {
- throw new InvalidOperationException($"Tag transfer type and element transfer type are not matched. Tag:{tag}");
- }
- Tag = tag;
- Element = element;
- }
- public Message()
- {
- CreateId = Guid.NewGuid().ToString();
- }
- protected Message(Message message) : this()
- {
- Tag = message.Tag;
- Element = message.Element;
- }
- /// <summary>
- /// Set Message Tag and Element value
- /// </summary>
- public void SetTagAndElement(MessageTag messageTag, IElement element)
- {
- Tag = messageTag;
- Element = element;
- }
- /// <summary>
- /// Buffer = Version|Tag|Element
- /// </summary>
- /// <returns></returns>
- public virtual IBuffer GetBuffer()
- {
- var tagBuffer = Tag.GetBuffer();
- var elementBuffer = Element.GetBuffer();
- var buffer = new CompositBuffer();
- buffer.Add(tagBuffer);
- buffer.Add(elementBuffer);
- return buffer;
- }
- /// <summary>
- /// Get message version
- /// 0 - older version, 1- new version string element will be encrypt and Decrypt
- /// </summary>
- /// <returns></returns>
- public int GetVersion()
- {
- if (Element is DictionaryElement dictionaryElement)
- {
- if (dictionaryElement.Value.ContainsKey(SystemTags.Version))
- {
- var element = dictionaryElement.Value[SystemTags.Version].Element;
- if (element is IntegerElement integerElement)
- {
- return integerElement.Value;
- }
- }
- }
- return 0;
- }
- public bool ExistVersion()
- {
- if (Element is DictionaryElement dictionaryElement)
- {
- if (dictionaryElement.Value.ContainsKey(SystemTags.Version))
- {
- var element = dictionaryElement.Value[SystemTags.Version].Element;
- if (element is IntegerElement integerElement)
- {
- return true;
- }
- }
- }
- return false;
- }
- /// <summary>
- /// Set message version
- /// </summary>
- /// <param name="version"></param>
- public void SetVersion(int version)
- {
- if (Element is DictionaryElement dictionaryElement)
- {
- if (!dictionaryElement.Value.ContainsKey(SystemTags.Version))
- {
- dictionaryElement.AddMessage(SystemTags.Version, new IntegerElement(version));
- }
- }
- }
- /// <summary>
- /// Set message AccountId
- /// </summary>
- /// <param name="version"></param>
- public void SetAccountBaseId(string accountBaseId)
- {
- if (Element is DictionaryElement dictionaryElement)
- {
- if (!dictionaryElement.Value.ContainsKey(SystemTags.AccountBaseId))
- {
- dictionaryElement.AddMessage(SystemTags.AccountBaseId, new StringElement(DesBuilder.Encrypt(accountBaseId)));
- }
- }
- }
- /// <summary>
- /// Get message AccountId
- /// </summary>
- /// <returns></returns>
- public string GetAccountId()
- {
- if (Element is DictionaryElement dictionaryElement)
- {
- if (dictionaryElement.Value.ContainsKey(SystemTags.AccountBaseId))
- {
- var element = dictionaryElement.Value[SystemTags.AccountBaseId].Element;
- if (element is StringElement stringElement)
- {
- return stringElement.Value;
- }
- }
- }
- return string.Empty;
- }
- /// <summary>
- /// Try convert a buffer to a Message.
- /// </summary>
- /// <param name="buffer">The buffer to be converted.</param>
- /// <returns>The converted Message</returns>
- private static Message ReadMessage(IBuffer buffer)
- {
- var messageBuffer = buffer as CompositBuffer;
- if (messageBuffer == null || messageBuffer.Buffers.Length != MessageBuffers)
- {
- throw new InvalidOperationException("Read message error.");
- }
- var tag = CreateTag(messageBuffer.Buffers[0]);
- var element = CreateElement(messageBuffer.Buffers[1]);
- var message = new Message(tag, element);
- return message;
- }
- /// <summary>
- /// Create a related Tag according to the TagId.
- /// </summary>
- /// <param name="buffer">The buffer of TagId</param>
- /// <returns>The converted Tag</returns>
- /// <remarks>The Tag mush be registerd into the MessageTag so that this method can get the right tag.</remarks>
- private static MessageTag CreateTag(IBuffer buffer)
- {
- var tagBuffer = buffer as CompositBuffer;
- if (tagBuffer == null || tagBuffer.Buffers.Length != TagBuffers)
- {
- throw new InvalidOperationException("Read tag error.");
- }
- var tagId = BitConverter.ToInt32(tagBuffer.Buffers[0].GetBytes(), 0);
- var transferType = (TransferType)BitConverter.ToInt32(tagBuffer.Buffers[1].GetBytes(), 0);
- var tag = MessageTag.GetRegisteredTag(tagId);
- if (tag == null)
- {
- throw new InvalidOperationException($"Can not get tag, tagId : {tagId}");
- }
- if (tag.TransferType != transferType)
- {
- throw new InvalidOperationException($"Tag transferType not matched.tagId:{tagId}, tag description:{tag.Description}, tag type:{tag.TransferType}, type:{transferType}");
- }
- return tag;
- }
- /// <summary>
- /// Create the Element from buffer.
- /// </summary>
- /// <param name="buffer">The buffer to be converted.</param>
- /// <returns>The converted Element.</returns>
- private static IElement CreateElement(IBuffer buffer)
- {
- var elementBuffer = buffer as CompositBuffer;
- if (elementBuffer == null || elementBuffer.Buffers.Length != ElementBuffers)
- {
- throw new InvalidOperationException("Read element error.");
- }
- var transferType = (TransferType)BitConverter.ToInt32(elementBuffer.Buffers[0].GetBytes(), 0);
- return CreateElement(transferType, elementBuffer.Buffers[1]);
- }
- /// <summary>
- /// Create the element according to the transferType and buffer.
- /// </summary>
- /// <param name="transferType"></param>
- /// <param name="buffer"></param>
- /// <returns></returns>
- private static IElement CreateElement(TransferType transferType, IBuffer buffer)
- {
- IElement element = null;
- switch (transferType)
- {
- case TransferType.Empty:
- element = CreateEmptyElement(buffer);
- break;
- case TransferType.Integer:
- element = CreateInegerElement(buffer);
- break;
- case TransferType.Long:
- element = CreateLongElement(buffer);
- break;
- case TransferType.Float:
- element = CreateFloatElement(buffer);
- break;
- case TransferType.Double:
- element = CreateDoubleElement(buffer);
- break;
- case TransferType.Bool:
- element = CreateBoolElement(buffer);
- break;
- case TransferType.DateTime:
- element = CreateDateTimeElement(buffer);
- break;
- case TransferType.String:
- element = CreateStringElement(buffer);
- break;
- case TransferType.Binary:
- element = CreateBufferElement(buffer);
- break;
- case TransferType.List:
- element = CreateListElement(buffer);
- break;
- case TransferType.Dictionary:
- element = CreateDictionaryElement(buffer);
- break;
- case TransferType.Id:
- element = CreateIdElement(buffer);
- break;
- }
- if (element == null)
- {
- throw new InvalidOperationException("Create element error");
- }
- return element;
- }
- private static IElement CreateEmptyElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- if (buffer.Size != 0)
- {
- throw new InvalidCastException("Buffer is not empty, element may not be the EmptyElement.");
- }
- var element = new EmptyElement();
- return element;
- }
- private static IElement CreateInegerElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var element = new IntegerElement(0);
- var value = BitConverter.ToInt32(buffer.GetBytes(), 0);
- element.Value = value;
- return element;
- }
- private static IElement CreateLongElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var element = new LongElement(0);
- var value = BitConverter.ToInt64(buffer.GetBytes(), 0);
- element.Value = value;
- return element;
- }
- private static IElement CreateFloatElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var element = new FloatElement(0.0f);
- var value = BitConverter.ToSingle(buffer.GetBytes(), 0);
- element.Value = value;
- return element;
- }
- private static IElement CreateDoubleElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var element = new DoubleElement(0.0f);
- var value = BitConverter.ToDouble(buffer.GetBytes(), 0);
- element.Value = value;
- return element;
- }
- private static IElement CreateBoolElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var element = new BoolElement(false);
- var value = BitConverter.ToBoolean(buffer.GetBytes(), 0);
- element.Value = value;
- return element;
- }
- private static IElement CreateDateTimeElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var element = new DateTimeElement(DateTime.Now);
- var value = BitConverter.ToInt64(buffer.GetBytes(), 0);
- element.Value = DateTime.FromBinary(value);
- return element;
- }
- private static IElement CreateStringElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var element = new StringElement(string.Empty);
- var data = buffer.GetBytes();
- var value = Encoding.UTF8.GetString(data, 0, data.Length);
- element.Value = value;
- return element;
- }
- private static IElement CreateBufferElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var element = new BufferElement(buffer);
- return element;
- }
- private static IElement CreateListElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var cb = buffer as CompositBuffer;
- if (cb == null)
- {
- throw new InvalidOperationException("Read list element error.");
- }
- var messages = cb.Buffers.Select(ReadMessage).ToList();
- var element = new ListElement();
- foreach (var message in messages)
- {
- element.AddMessage(message);
- }
- return element;
- }
- private static IElement CreateDictionaryElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var cb = buffer as CompositBuffer;
- if (cb == null)
- {
- throw new InvalidOperationException("Read dictionary element error.");
- }
- var messages = cb.Buffers.Select(ReadMessage).ToList();
- var element = new DictionaryElement();
- foreach (var message in messages)
- {
- element.AddMessage(message);
- }
- return element;
- }
- private static IElement CreateIdElement(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- var id = new FasterUId(buffer.GetBytes());
- var element = new IdElement(id);
- return element;
- }
- /// <summary>
- /// Convert buffer to Message
- /// </summary>
- /// <param name="buffer">The buffer to be converted.</param>
- /// <returns>The converted Message</returns>
- public static Message FromBuffer(IBuffer buffer)
- {
- if (buffer == null) throw new ArgumentNullException(nameof(buffer));
- return ReadMessage(buffer);
- }
- public override string ToString()
- {
- var sb = new StringBuilder();
- sb.Append($"<Message tag=\"{Tag}\">");
- sb.Append($"{Element}");
- sb.Append("</Message>");
- return sb.ToString();
- }
- public void Dispose()
- {
- this.Dispose(true);
- }
- protected virtual void Dispose(bool disposing)
- {
- if (!IsDisposed)
- {
- MessagePool.Recover(this);
- IsDisposed = true;
- }
- }
- }
- }
|