RulesEngine/src/RulesEngine/HelperFunctions/Utils.cs

128 lines
4.3 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Linq.Dynamic.Core;
namespace RulesEngine.HelperFunctions
{
public static class Utils
{
public static object GetTypedObject(dynamic input)
{
if (input is ExpandoObject)
{
Type type = CreateAbstractClassType(input);
return CreateObject(type, input);
}
else
{
return input;
}
}
public static Type CreateAbstractClassType(dynamic input)
{
List<DynamicProperty> props = new List<DynamicProperty>();
if (input == null)
{
return typeof(object);
}
if (!(input is ExpandoObject))
{
return input.GetType();
}
else
{
foreach (var expando in (IDictionary<string, object>)input)
{
Type value;
if (expando.Value is IList)
{
if (((IList)expando.Value).Count == 0)
value = typeof(List<object>);
else
{
var internalType = CreateAbstractClassType(((IList)expando.Value)[0]);
value = new List<object>().Cast(internalType).ToList(internalType).GetType();
}
}
else
{
value = CreateAbstractClassType(expando.Value);
}
props.Add(new DynamicProperty(expando.Key, value));
}
}
var type = DynamicClassFactory.CreateType(props);
return type;
}
public static object CreateObject(Type type, dynamic input)
{
if (!(input is ExpandoObject))
{
return Convert.ChangeType(input, type);
}
object obj = Activator.CreateInstance(type);
foreach (var expando in (IDictionary<string, object>)input)
{
if (type.GetProperties().Any(c => c.Name == expando.Key) &&
expando.Value != null && (expando.Value.GetType().Name != "DBNull" || expando.Value != DBNull.Value))
{
object val;
if (expando.Value is ExpandoObject)
{
var propType = type.GetProperty(expando.Key).PropertyType;
val = CreateObject(propType, expando.Value);
}
else if (expando.Value is IList)
{
var internalType = type.GetProperty(expando.Key).PropertyType.GenericTypeArguments.FirstOrDefault() ?? typeof(object);
var temp = (IList)expando.Value;
var newList = new List<object>();
for (int i = 0; i < temp.Count; i++)
{
var child = CreateObject(internalType, temp[i]);
newList.Add(child);
};
val = newList.Cast(internalType).ToList(internalType);
}
else
{
val = expando.Value;
}
type.GetProperty(expando.Key).SetValue(obj, val, null);
}
}
return obj;
}
private static IEnumerable Cast(this IEnumerable self, Type innerType)
{
var methodInfo = typeof(Enumerable).GetMethod("Cast");
var genericMethod = methodInfo.MakeGenericMethod(innerType);
return genericMethod.Invoke(null, new[] { self }) as IEnumerable;
}
private static IList ToList(this IEnumerable self, Type innerType)
{
var methodInfo = typeof(Enumerable).GetMethod("ToList");
var genericMethod = methodInfo.MakeGenericMethod(innerType);
return genericMethod.Invoke(null, new[] { self }) as IList;
}
}
}