aurora/aurora-sharp-desktop/Aurora/Utils/ReflectionUtils.cs
2021-03-05 23:10:12 -05:00

78 lines
2.3 KiB
C#

using System;
using System.Linq;
using System.Reflection;
namespace Aurora.Utils
{
public static class ReflectionUtils
{
private const char IndexBeginOp = '[';
private const char IndexEndOp = ']';
private const char PropertyOfOp = '.';
public static object GetValueByPath(object obj, string path)
{
object result = obj;
var tokens = path?.Split(IndexBeginOp, PropertyOfOp).ToList();
foreach (var token in tokens)
{
if (result == null)
break;
// Property
if (!token.Contains(IndexEndOp.ToString()))
{
result = GetPropertyValue(result, token);
}
// Index
else
{
result = GetIndexValue(result, token.Replace(IndexEndOp.ToString(), ""));
}
}
return result;
}
private static object GetPropertyValue(object obj, string propertyName)
{
try
{
return obj?.GetType().GetRuntimeProperty(propertyName)?.GetValue(obj);
}
catch
{
return null;
}
}
private static object GetIndexValue(object obj, string index)
{
object result = null;
var indexOperator = obj?.GetType().GetRuntimeProperty("Item");
if (indexOperator != null)
{
var indexParameters = indexOperator.GetIndexParameters();
// Looking up suitable index operator
foreach (var parameter in indexParameters)
{
bool isIndexOpWorked = true;
try
{
var indexVal = Convert.ChangeType(index, parameter.ParameterType);
result = indexOperator.GetValue(obj, new object[] { indexVal });
}
catch
{
isIndexOpWorked = false;
}
// If the index operator worked, skip looking up others
if (isIndexOpWorked)
break;
}
}
return result;
}
}
}