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;
}
}
}