114 lines
3.5 KiB
C#
114 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using ln.http.exceptions;
|
|
using System.IO;
|
|
using System.Text;
|
|
namespace ln.http.resources.reflection
|
|
{
|
|
public class Reflector
|
|
{
|
|
Type TargetType { get; }
|
|
|
|
Dictionary<string, PropertyInfo> properties = new Dictionary<string, PropertyInfo>();
|
|
Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>();
|
|
|
|
public Reflector(Type targetType)
|
|
{
|
|
TargetType = targetType;
|
|
Initialize();
|
|
}
|
|
|
|
private void Initialize()
|
|
{
|
|
foreach (PropertyInfo propertyInfo in TargetType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
|
{
|
|
if (propertyInfo.GetCustomAttribute<CallableAttribute>() != null)
|
|
{
|
|
properties.Add(propertyInfo.Name, propertyInfo);
|
|
}
|
|
}
|
|
foreach (MethodInfo methodInfo in TargetType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
|
|
{
|
|
if (methodInfo.GetCustomAttribute<CallableAttribute>() != null)
|
|
{
|
|
methods.Add(methodInfo.Name, methodInfo);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public object InvokeRequest(HttpRequest httpRequest, Queue<string> pathStack, object currentValue)
|
|
{
|
|
if (pathStack.Count == 0)
|
|
return currentValue;
|
|
|
|
StringReader reader = new StringReader(pathStack.Dequeue());
|
|
StringBuilder sb = new StringBuilder();
|
|
while (IsValidNameChar((char)reader.Peek()))
|
|
sb.Append((char)reader.Read());
|
|
|
|
string next = sb.ToString();
|
|
sb.Clear();
|
|
|
|
if (properties.ContainsKey(next))
|
|
{
|
|
currentValue = properties[next].GetValue(currentValue);
|
|
}
|
|
else
|
|
{
|
|
throw new KeyNotFoundException(next);
|
|
}
|
|
|
|
while (reader.Peek() != -1)
|
|
{
|
|
char nc = (char)reader.Read();
|
|
switch (nc)
|
|
{
|
|
case '[':
|
|
while ((reader.Peek() != ']') && (reader.Peek() != -1))
|
|
sb.Append((char)reader.Read());
|
|
reader.Read();
|
|
|
|
string index = sb.ToString();
|
|
sb.Clear();
|
|
|
|
Type currentType = currentValue.GetType();
|
|
if (currentType.IsArray)
|
|
{
|
|
int i = int.Parse(index);
|
|
currentValue = ((Array)currentValue).GetValue(i);
|
|
}
|
|
else
|
|
{
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
break;
|
|
default:
|
|
throw new NotSupportedException();
|
|
}
|
|
}
|
|
|
|
return currentValue;
|
|
}
|
|
|
|
|
|
public static bool IsValidNameChar(char ch)
|
|
{
|
|
return Char.IsLetterOrDigit(ch) | (ch == '_');
|
|
}
|
|
|
|
|
|
static Dictionary<Type, Reflector> reflectorsCache = new Dictionary<Type, Reflector>();
|
|
public static Reflector GetReflector(Type targetType)
|
|
{
|
|
if (!reflectorsCache.ContainsKey(targetType))
|
|
{
|
|
reflectorsCache[targetType] = new Reflector(targetType);
|
|
}
|
|
return reflectorsCache[targetType];
|
|
}
|
|
}
|
|
}
|