// Copyright © 2020 The CefSharp Authors. All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.Serialization; namespace CefSharp.DevTools { /// /// Common Base class for DevTools Domain Model classes /// [DataContract] public abstract class DevToolsDomainEntityBase { #if NETCOREAPP internal static string EnumToString(Enum e) { var memberInfo = e.GetType().GetMember(e.ToString()).FirstOrDefault(); var enumMemberAttribute = (System.Text.Json.Serialization.JsonPropertyNameAttribute)Attribute.GetCustomAttribute(memberInfo, typeof(System.Text.Json.Serialization.JsonPropertyNameAttribute), false); return enumMemberAttribute.Name; } internal static string EnumToString(Array enumArray) { var returnValue = "["; foreach (var e in enumArray) { var memberInfo = e.GetType().GetMember(e.ToString()).FirstOrDefault(); var enumMemberAttribute = (System.Text.Json.Serialization.JsonPropertyNameAttribute)Attribute.GetCustomAttribute(memberInfo, typeof(System.Text.Json.Serialization.JsonPropertyNameAttribute), false); returnValue += enumMemberAttribute.Name + ","; } returnValue += returnValue.Substring(0, returnValue.Length - 1) + "]"; return returnValue; } #else internal static object StringToEnum(Type enumType, string input) { if (enumType.IsArray) { if (string.IsNullOrEmpty(input) || input == "[]" || input == "[ ]") { return null; //return Array.CreateInstance(enumType.GetElementType(), 0); } var values = input.Substring(1, input.Length - 2).Split(','); var returnValues = Array.CreateInstance(enumType.GetElementType(), values.Length); for (int i = 0; i < values.Length; i++) { var str = values[i].Trim('\r', '\n', '"', ' '); var enumVal = StringToEnumInternal(enumType.GetElementType(), str); returnValues.SetValue(enumVal, i); } return returnValues; } if (enumType.IsGenericType && enumType.GetGenericTypeDefinition() == typeof(Nullable<>)) { if (string.IsNullOrEmpty(input)) { return null; } enumType = Nullable.GetUnderlyingType(enumType); } return StringToEnumInternal(enumType, input); } private static object StringToEnumInternal(Type enumType, string input) { foreach (var name in Enum.GetNames(enumType)) { var enumMemberAttribute = ((EnumMemberAttribute[])enumType.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true)).Single(); if (enumMemberAttribute.Value == input) { return Enum.Parse(enumType, name); } } return (Enum.GetValues(enumType).GetValue(0)); } internal static string EnumToString(Enum e) { var memberInfo = e.GetType().GetMember(e.ToString()).FirstOrDefault(); var enumMemberAttribute = (EnumMemberAttribute)Attribute.GetCustomAttribute(memberInfo, typeof(EnumMemberAttribute), false); return enumMemberAttribute.Value; } internal static string EnumToString(Array enumArray) { var returnValue = "["; foreach (var e in enumArray) { var memberInfo = e.GetType().GetMember(e.ToString()).FirstOrDefault(); var enumMemberAttribute = (EnumMemberAttribute)Attribute.GetCustomAttribute(memberInfo, typeof(EnumMemberAttribute), false); returnValue += enumMemberAttribute.Value + ","; } returnValue += returnValue.Substring(0, returnValue.Length - 1) + "]"; return returnValue; } #endif #if NETCOREAPP public IDictionary ToDictionary() { var dict = new Dictionary(); var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { var propertyAttribute = (System.Text.Json.Serialization.JsonPropertyNameAttribute)Attribute.GetCustomAttribute(prop, typeof(System.Text.Json.Serialization.JsonPropertyNameAttribute), false); //Only add members that have JsonPropertyNameAttribute if (propertyAttribute == null) { continue; } var propertyName = propertyAttribute.Name; var propertyRequired = Attribute.IsDefined(prop, typeof(System.Diagnostics.CodeAnalysis.DisallowNullAttribute)); var propertyValue = prop.GetValue(this); if (propertyRequired && propertyValue == null) { throw new DevToolsClientException(prop.Name + " is required"); } //Not required and value null, don't add to dictionary if (propertyValue == null) { continue; } var propertyValueType = propertyValue.GetType(); if (typeof(DevToolsDomainEntityBase).IsAssignableFrom(propertyValueType)) { propertyValue = ((DevToolsDomainEntityBase)(propertyValue)).ToDictionary(); } else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(IList<>) && typeof(DevToolsDomainEntityBase).IsAssignableFrom(prop.PropertyType.GetGenericArguments()[0])) { var values = new List>(); foreach (var value in (IEnumerable)propertyValue) { values.Add(((DevToolsDomainEntityBase)value).ToDictionary()); } propertyValue = values; } else if (propertyValueType.IsEnum) { propertyValue = EnumToString((Enum)propertyValue); } else if (propertyValueType.IsGenericType) { var nullableType = Nullable.GetUnderlyingType(propertyValueType); if(nullableType != null && nullableType.IsEnum) { propertyValue = EnumToString((Enum)propertyValue); } } else if (propertyValueType.IsArray && propertyValueType.GetElementType().IsEnum) { propertyValue = EnumToString((Array)propertyValue); } dict.Add(propertyName, propertyValue); } return dict; } #else public IDictionary ToDictionary() { var dict = new Dictionary(); var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var prop in properties) { var dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(prop, typeof(DataMemberAttribute), false); //Only add members that have DataMemberAttribute if (dataMemberAttribute == null) { continue; } var propertyName = dataMemberAttribute.Name; var propertyRequired = dataMemberAttribute.IsRequired; var propertyValue = prop.GetValue(this); if (propertyRequired && propertyValue == null) { throw new DevToolsClientException(prop.Name + " is required"); } //Not required and value null, don't add to dictionary if (propertyValue == null) { continue; } var propertyValueType = propertyValue.GetType(); if (typeof(DevToolsDomainEntityBase).IsAssignableFrom(propertyValueType)) { propertyValue = ((DevToolsDomainEntityBase)(propertyValue)).ToDictionary(); } else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(IList<>) && typeof(DevToolsDomainEntityBase).IsAssignableFrom(prop.PropertyType.GetGenericArguments()[0])) { var values = new List>(); foreach (var value in (IEnumerable)propertyValue) { values.Add(((DevToolsDomainEntityBase)value).ToDictionary()); } propertyValue = values; } dict.Add(propertyName, propertyValue); } return dict; } #endif } }