Archived
Private
Public Access
1
0
This repository has been archived on 2026-02-04. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ProjectBackup/C#/DynamicParser/ExpandoParser.cs
2023-07-31 21:20:56 +02:00

182 lines
7.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Reflection;
namespace DynamicParser {
public static class ExpandoParser {
public static ExpandoObject ToExpando(in object @object) {
var properties = @object.GetType().GetProperties();
IDictionary<string, object> expando = new ExpandoObject();
foreach (var property in properties) {
var value = GetValueOrExpandoObject(@object, property);
expando.Add(property.Name, value);
}
return (ExpandoObject)expando;
}
private static object GetValueOrExpandoObject(in object @object, in PropertyInfo property) {
var value = property.GetValue(@object);
if (value == null) return null;
var valueType = value.GetType();
if (valueType.IsValueType || value is string) return value;
if (value is IList && value.GetType().IsGenericType &&
value.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(List<>)))
return ToExpandoCollection(value as IList);
if (value is IDictionary && value.GetType().IsGenericType &&
value.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>)))
return ToExpandoCollection(value as IDictionary);
return ToExpando(value);
}
private static List<object> ToExpandoCollection(in IList enumerable) {
var list = new List<object>();
foreach (object obj in enumerable) {
if (obj.GetType().IsValueType || obj is string) list.Add(obj);
else list.Add(ToExpando(obj));
}
return list;
}
private static Dictionary<object, object> ToExpandoCollection(in IDictionary enumerable) {
var dict = new Dictionary<object, object>();
foreach (var key in enumerable.Keys) {
var value = enumerable[key];
if (value.GetType().IsValueType || value is string) dict.Add(key, value);
else dict.Add(key, ToExpando(value));
}
return dict;
}
public static void PrintDynamic(in ExpandoObject data, in string prefix = "", in Type type = null) {
var dict = new Dictionary<object, object>();
foreach (var pair in data) {
dict.Add(pair.Key, pair.Value);
}
PrintDict(dict, prefix, type);
}
private static void PrintDict(in Dictionary<object, object> data, string prefix = "", in Type type = null) {
if (type != null) {
Console.WriteLine(prefix + type);
prefix += "\t";
}
foreach (var element in data) {
Console.WriteLine($"{prefix}{element.Key}: {element.Value ?? "null"}");
if (element.Value is null) continue;
if (element.Value.GetType() == typeof(ExpandoObject)) {
PrintDynamic(element.Value as ExpandoObject, prefix + "\t");
}
if (element.Value.GetType() == typeof(List<object>)) {
var list = element.Value as List<object> ?? new List<object>();
foreach (var e in list) {
if (e.GetType() == typeof(ExpandoObject))
PrintDynamic(e as ExpandoObject, prefix + "\t", e.GetType());
else Console.WriteLine(prefix + "\t" + e);
}
}
if (element.Value.GetType() == typeof(Dictionary<object, object>)) {
PrintDict(element.Value as Dictionary<object, object>, prefix + "\t");
}
}
}
public static T ToObject<T>(in ExpandoObject @object) where T : new() {
T result = Activator.CreateInstance<T>();
var properties = result.GetType().GetProperties();
foreach (var property in properties) {
property.SetValue(result, GetValue(@object, property));
}
return result;
}
private static object ToObject(in Type type, in ExpandoObject @object) {
var result = Activator.CreateInstance(type);
var properties = type.GetProperties();
foreach (var property in properties) {
property.SetValue(result, GetValue(@object, property));
}
return result;
}
private static object GetValue(in ExpandoObject @object, in PropertyInfo property) {
var value = ((IDictionary<string, object>)@object)[property.Name];
if (value == null) return default;
var vType = value.GetType();
if (vType.IsValueType || value is string) return value;
var expandoType = typeof(ExpandoObject);
if (vType == expandoType) {
return ToObject(property.PropertyType, value as ExpandoObject);
}
if (vType == typeof(List<object>)) {
var list = value as List<object> ?? new List<object>();
var type = property.PropertyType.GenericTypeArguments[0];
var enumerableType = typeof(Enumerable);
var castMethod = enumerableType.GetMethod(nameof(Enumerable.Cast))?.MakeGenericMethod(type);
var toListMethod = enumerableType.GetMethod(nameof(Enumerable.ToList))?.MakeGenericMethod(type);
IEnumerable<object> itemsToCast;
itemsToCast = list.Select(item => {
if (item.GetType() == expandoType)
return ToObject(type, item as ExpandoObject);
return Convert.ChangeType(item, type);
});
var castedItems = castMethod.Invoke(null, new[] { itemsToCast });
return toListMethod.Invoke(null, new[] { castedItems });
}
if (vType == typeof(Dictionary<object, object>)) {
var dict = value as Dictionary<object, object> ?? new Dictionary<object, object>();
var keyType = property.PropertyType.GenericTypeArguments[0];
var valueType = property.PropertyType.GenericTypeArguments[1];
var dictType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
var output = Activator.CreateInstance(dictType) as IDictionary ?? new Dictionary<object, object>();
foreach (var pair in dict) {
object k;
object v;
if (pair.Key.GetType() == expandoType)
k = ToObject(keyType, pair.Key as ExpandoObject);
else k = Convert.ChangeType(pair.Key, keyType);
if (pair.Value.GetType() == expandoType)
v = ToObject(valueType, pair.Value as ExpandoObject);
else v = Convert.ChangeType(pair.Value, valueType);
output.Add(k, v);
}
return output;
}
return default;
}
}
}