sharp-application-server/resources/reflection/ReflectiveResourceCrawler.cs

113 lines
3.7 KiB
C#

using System;
using System.Collections.Generic;
using appsrv.server;
using System.Reflection;
using appsrv.exceptions;
using appsrv.attributes;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
namespace appsrv.resources.reflection
{
public class ReflectiveResourceCrawler
{
/* Instance Members */
public ReflectiveResource Resource { get; }
public Type NativeType { get; }
public ReflectiveResourceCrawler(ReflectiveResource resource,Type type)
{
Resource = resource;
NativeType = type;
}
public object Crawl(object instance,Request request,Stack<String> pathStack)
{
if (pathStack.Count == 0)
return instance;
String next = pathStack.Pop();
foreach (FieldInfo fieldInfo in NativeType.GetFields())
{
if (fieldInfo.GetCustomAttribute<PublishedMemberAttribute>()!=null)
{
if (fieldInfo.Name.Equals(next))
{
return FixupIntermediate(fieldInfo.GetValue(instance), request, pathStack);
}
}
}
foreach (PropertyInfo propertyInfo in NativeType.GetProperties())
{
if (propertyInfo.GetCustomAttribute<PublishedMemberAttribute>() != null)
{
if (propertyInfo.Name.Equals(next))
{
return FixupIntermediate(propertyInfo.GetValue(instance), request, pathStack);
}
}
}
foreach (MethodInfo methodInfo in NativeType.GetMethods())
{
if (methodInfo.GetCustomAttribute<PublishedMemberAttribute>() != null)
{
if (methodInfo.Name.Equals(next))
{
object[] parameters = PopParameters(methodInfo,pathStack,request);
object i = methodInfo.IsStatic ? null : instance;
return FixupIntermediate( methodInfo.Invoke(i,parameters), request, pathStack);
}
}
}
throw new KeyNotFoundException(next);
}
private object[] PopParameters(MethodInfo methodInfo,Stack<String> pathStack,Request request)
{
ParameterInfo[] parameterInfos = methodInfo.GetParameters();
object[] p = new object[parameterInfos.Length];
for (int n = 0; n < parameterInfos.Length;n++)
{
string nextparm = null;
if (request.HasParameter(parameterInfos[n].Name))
{
nextparm = request.GetParameterValue(parameterInfos[n].Name);
} else
{
if (pathStack.Count > 0)
{
nextparm = pathStack.Pop();
}
}
p[n] = Convert.ChangeType(nextparm, parameterInfos[n].ParameterType);
}
return p;
}
private object FixupIntermediate(object intermediate,Request request, Stack<String> pathStack)
{
if (intermediate.GetType().IsArray)
return FixupIntermediateArray((Array)intermediate, request, pathStack);
return intermediate;
}
private object FixupIntermediateArray(Array intermediate, Request request, Stack<String> pathStack)
{
if (pathStack.Count == 0)
return intermediate;
int index = int.Parse(pathStack.Pop());
return intermediate.GetValue(index);
}
}
}