using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Vinno.IUS.Common.Network.Transfer { public class DictionaryMessage : Message { public DictionaryMessage(MessageTag tag) : base(tag, new DictionaryElement()) { } public DictionaryMessage(Message message) : base(message) { } ~DictionaryMessage() { Dispose(false); } protected DictionaryMessage() { var messageTag =TransferMessageHelper.GetMessageTagByType(GetType()); SetTagAndElement(messageTag, new DictionaryElement()); } public bool HasTag(MessageTag tag) { var dictionary = (DictionaryElement)Element; return dictionary.Value.ContainsKey(tag); } /// /// Add message into dictionary /// /// public void AddMessage(Message message) { var dictionary = (DictionaryElement)Element; dictionary.AddMessage(message); } /// /// Add message into dictionary /// /// /// public void AddMessage(MessageTag tag, IElement element) { var dictionary = (DictionaryElement)Element; dictionary.AddMessage(tag, element); } /// /// Gets message of this dictionary. /// /// /// public Message GetMessage(MessageTag tag) { var dictionary = (DictionaryElement)Element; if (dictionary.Value.ContainsKey(tag)) { return dictionary.Value[tag]; } throw new InvalidOperationException($"Tag:{tag} does not exist."); } /// /// Gets the element by message tag. /// /// /// /// public T GetElement(MessageTag tag) where T : IElement { var dictionary = (DictionaryElement)Element; if (dictionary.Value.ContainsKey(tag)) { var element = dictionary.Value[tag].Element; if (element is T) { return (T)element; } throw new InvalidOperationException($"ElementType:{element.GetType()} should be {typeof(T)}."); } throw new InvalidOperationException($"Tag:{tag} does not exist."); } protected override void Dispose(bool disposing) { if (!IsDisposed) { SetTagAndElement(Tag, new DictionaryElement()); } base.Dispose(disposing); } protected static T ConvertToMessage(Message message) where T : DictionaryMessage { var type = typeof(T); var messageTag = TransferMessageHelper.GetMessageTagByType(type); if (messageTag == null || messageTag.Id != message.Tag.Id) { return null; } if (MessagePool.GetMessage() is DictionaryMessage createdictionarymessage) { if (((DictionaryElement)message.Element)?.Value.Count <= 0) { TransferMessageHelper.SetMessageProperties(message); } createdictionarymessage.SetTagAndElement(message.Tag, message.Element); var properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { var attributes = propertyInfo.GetCustomAttributes().Cast(); foreach (var attribute in attributes) { var value = GetMessagePropertyValue(createdictionarymessage, attribute, propertyInfo); if (value != null) { propertyInfo.SetValue(createdictionarymessage, value, null); //set message property value } } } return createdictionarymessage as T; } return null; } private static object GetMessagePropertyValue(DictionaryMessage dictionaryMessage, CustomMessageAttribute customMessageAttribute, PropertyInfo property) { var messageTag = MessageTag.GetRegisteredTag(customMessageAttribute.TagId); var transferType = messageTag.TransferType; var propertyType = property.PropertyType; object value = null; if (dictionaryMessage.HasTag(messageTag)) { switch (transferType) { case TransferType.String: var stringvalue = dictionaryMessage.GetElement(messageTag).Value; value = stringvalue; if (value==null) { value = string.Empty; } break; case TransferType.Integer: var integervalue = dictionaryMessage.GetElement(messageTag).Value; value = integervalue; break; case TransferType.Binary: var buffervalue = dictionaryMessage.GetElement(messageTag).Value; if (propertyType == typeof(byte[])) { value = buffervalue?.GetBytes(); } else { value = buffervalue; } break; case TransferType.Bool: var boolvalue = dictionaryMessage.GetElement(messageTag).Value; value = boolvalue; break; case TransferType.Float: var floatvalue = dictionaryMessage.GetElement(messageTag).Value; value = floatvalue; break; case TransferType.DateTime: var dateTimevalue = dictionaryMessage.GetElement(messageTag).Value; value = dateTimevalue; break; case TransferType.Long: var longvalue = dictionaryMessage.GetElement(messageTag).Value; value = longvalue; break; case TransferType.Double: var doublevalue = dictionaryMessage.GetElement(messageTag).Value; value = doublevalue; break; case TransferType.Id: var id = dictionaryMessage.GetElement(messageTag).Value; value = id; break; case TransferType.List: var listElementvalue = dictionaryMessage.GetElement(messageTag).Value .ToList(); if (propertyType.IsGenericType) { Type[] genericArgTypes = propertyType.GetGenericArguments(); if (genericArgTypes.Length > 0) { int listElementTagId = 0; if (customMessageAttribute is MessageListMemberAttribute messagelistMemberAttribute) { listElementTagId = messagelistMemberAttribute.SubTagId; } var listElementMessageTag = MessageTag.GetRegisteredTag(listElementTagId); var genericArgType = genericArgTypes[0]; Type listType = typeof(List<>).MakeGenericType(genericArgType); var list = (IList)Activator.CreateInstance(listType); foreach (var childMessage in listElementvalue) { object childvalue = null; switch (listElementMessageTag.TransferType) { case TransferType.String: childvalue = (childMessage.Element as StringElement)?.Value; break; case TransferType.Integer: childvalue = (childMessage.Element as IntegerElement)?.Value; break; case TransferType.Binary: childvalue = (childMessage.Element as BufferElement)?.Value; break; case TransferType.Bool: childvalue = (childMessage.Element as BoolElement)?.Value; break; case TransferType.DateTime: childvalue = (childMessage.Element as DateTimeElement)?.Value; break; case TransferType.Double: childvalue = (childMessage.Element as DoubleElement)?.Value; break; case TransferType.Float: childvalue = (childMessage.Element as FloatElement)?.Value; break; case TransferType.Long: childvalue = (childMessage.Element as LongElement)?.Value; break; case TransferType.Id: childvalue = (childMessage.Element as IdElement)?.Value; break; case TransferType.Dictionary: var methodElement = genericArgType.GetMethod("Convert"); if (methodElement != null) { childvalue = methodElement.Invoke(null, new[] { childMessage }); } break; } if (childvalue != null) { list.Add(childvalue); } } value = list; } } break; case TransferType.Dictionary: if (dictionaryMessage.HasTag(messageTag)) { var propertyMessage = dictionaryMessage.GetMessage(messageTag); var method = propertyType.GetMethod("Convert"); if (method != null) { var valueMessage = (Message)method.Invoke(null, new[] { propertyMessage }); value = valueMessage; } else { throw new InvalidOperationException($" Message: {propertyType} (Tag:{messageTag} ) no found Convet method "); } } break; } } return value; } } }