From 7c0987e424e9dfc691ecde66e7df1226978fba03 Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Thu, 4 Apr 2019 19:34:13 +0200 Subject: [PATCH] WIP --- ReflectiveResource.cs | 296 +++++++++++++++++++++++++++++++++++++++ Resource.cs | 2 + ln.http.resources.csproj | 5 + reflection/Reflector.cs | 60 ++++++++ 4 files changed, 363 insertions(+) create mode 100644 ReflectiveResource.cs create mode 100644 reflection/Reflector.cs diff --git a/ReflectiveResource.cs b/ReflectiveResource.cs new file mode 100644 index 0000000..0050c79 --- /dev/null +++ b/ReflectiveResource.cs @@ -0,0 +1,296 @@ +// /** +// * File: JsonCallResource.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +using System.Reflection; +using System.Collections.Generic; +using Newtonsoft.Json; +using ln.http.exceptions; +using ln.logging; +using Newtonsoft.Json.Linq; +using System.Runtime.CompilerServices; +using System.Linq; +using System.Runtime.InteropServices; +using System.Diagnostics; +namespace ln.http.resources +{ + public abstract class ReflectiveResource : Resource + { + public override bool HandlesDispatching => true; + + + Dictionary callableMethods = new Dictionary(); + Dictionary properties = new Dictionary(); + + Dictionary reflectiveResources = new Dictionary(); + + public ReflectiveResource(Resource container, string name,object o) + : base(container, name) + { + initialize(); + } + + private void initialize() + { + Dictionary> callables = new Dictionary>(); + + foreach (MethodInfo methodInfo in this.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) + { + CallableAttribute callableAttribute = methodInfo.GetCustomAttribute(); + if (callableAttribute != null) + { + string alias = callableAttribute.Alias == null ? methodInfo.Name : callableAttribute.Alias; + if (!callables.ContainsKey(alias)) + { + callables.Add(alias, new List()); + } + callables[alias].Add(methodInfo); + } + } + + foreach (String alias in callables.Keys) + { + callableMethods.Add(alias, callables[alias].ToArray()); + new MethodResource(this, alias); + } + + foreach (PropertyInfo propertyInfo in this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) + { + if (propertyInfo.GetCustomAttribute() != null) + { + new CallableProperty(this, propertyInfo); + } + } + + } + + private object InvokeMethodCall(string methodName, object[] arguments) + { + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + + MethodInfo methodInfo = FindMethodSignature(methodName, arguments.Length); + object result = methodInfo.Invoke(this, arguments); + + stopwatch.Stop(); + Logging.Log(LogLevel.DEBUGDETAIL,"InvokeMethodCall({0},...): {1}ms",methodName,stopwatch.ElapsedMilliseconds); + + return result; + } + + private object InvokeMethodCall(string methodName, KeyValuePair[] arguments) + { + MethodInfo methodInfo = FindMethodSignature(methodName, arguments.Select((kvp) => kvp.Key).ToArray()); + Dictionary args = new Dictionary(); + foreach (KeyValuePair kvp in arguments) + args.Add(kvp.Key, kvp.Value); + + ParameterInfo[] parameterInfos = methodInfo.GetParameters(); + object[] pl = new object[parameterInfos.Length]; + + for (int n=0;n(httpRequest.ContentReader.ReadToEnd()); + MethodResult methodResult; + + try + { + methodResult = new MethodResult(); + methodResult.MethodName = methodCall.MethodName; + + methodResult.Result = InvokeMethodCall(methodCall.MethodName, methodCall.Parameters); + } catch (Exception e) + { + methodResult = new MethodResult(); + methodResult.MethodName = methodCall.MethodName; + methodResult.Exception = e; + Logging.Log(LogLevel.ERROR, "JsonCallResource: method call caught exception: {0}",e); + Logging.Log(e); + } + + String result = JsonConvert.SerializeObject(methodResult); + + HttpResponse httpResponse = new HttpResponse(httpRequest); + httpResponse.SetHeader("content-type", "application/json"); + httpResponse.ContentWriter.Write(result); + + return httpResponse; + } + + private string SerializeResult(MethodInfo methodInfo,MethodResult methodResult) + { + if (methodResult.Exception != null) + { + return JsonConvert.SerializeObject(methodResult); + } + else + { + return FlatSerializeResult(methodResult); + } + } + + private string FlatSerializeResult(MethodResult methodResult) + { + JObject jMethodResult = new JObject(); + jMethodResult.Add("Exception", null); + jMethodResult.Add("MethodName", methodResult.MethodName); + + JObject jResult = new JObject(); + jMethodResult.Add("Result", jResult); + + Type type = methodResult.GetType(); + + foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) + { + Type fType = fieldInfo.FieldType; + + if ((fType.IsValueType) || (typeof(string).Equals(fType)) || (fType.IsArray)) + { + jResult.Add(fieldInfo.Name, new JValue(fieldInfo.GetValue(methodResult.Result))); + } + else + { + jResult.Add(fieldInfo.Name, new JValue(fieldInfo.GetValue(methodResult.Result).ToString())); + } + } + + return jMethodResult.ToString(); + } + + + class MethodCall + { + public String MethodName; + public object[] Parameters; + } + + class MethodResult + { + public String MethodName; + public object Result; + public Exception Exception; + } + + + class MethodResource : Resource + { + public MethodResource(JsonCallResource container,String methodName) + :base(container,methodName) + { + } + + public override HttpResponse GetResponse(HttpRequest httpRequest) + { + throw new NotImplementedException(); + } + + + public override void AddResource(Resource resource) => throw new NotImplementedException(); + public override bool Contains(string name) => throw new NotImplementedException(); + public override IEnumerable GetResources() => throw new NotImplementedException(); + public override void RemoveResource(Resource resource) => throw new NotImplementedException(); + } + + class CallableProperty : Resource + { + public CallableProperty(JsonCallResource container, PropertyInfo propertyInfo) + : base(container, propertyInfo.Name) + { + this.propertyInfo = propertyInfo; + } + + PropertyInfo propertyInfo; + + public override void AddResource(Resource resource) => throw new NotImplementedException(); + public override void RemoveResource(Resource resource) => throw new NotImplementedException(); + + public override bool Contains(string name) => false; + public override IEnumerable GetResources() => new Resource[0]; + + public override HttpResponse GetResponse(HttpRequest httpRequest) + { + try + { + object v = propertyInfo.GetValue(Container); + String result = JsonConvert.SerializeObject(v); + + HttpResponse httpResponse = new HttpResponse(httpRequest); + httpResponse.SetHeader("content-type", "application/json"); + httpResponse.ContentWriter.Write(result); + + return httpResponse; + } catch (Exception e) + { + Logging.Log(e); + + HttpResponse httpResponse = new HttpResponse(httpRequest); + httpResponse.StatusCode = 500; + return httpResponse; + } + } + + } + + } +} diff --git a/Resource.cs b/Resource.cs index bd05d66..a96a7c2 100644 --- a/Resource.cs +++ b/Resource.cs @@ -10,6 +10,8 @@ namespace ln.http.resources public Resource Container { get; protected set; } public Resource DefaultResource { get; set; } + public virtual bool HandlesDispatching => false; + public Resource(String name) { Name = name; diff --git a/ln.http.resources.csproj b/ln.http.resources.csproj index 8b3498f..d2ac5e5 100644 --- a/ln.http.resources.csproj +++ b/ln.http.resources.csproj @@ -43,6 +43,8 @@ + + @@ -61,5 +63,8 @@ + + + \ No newline at end of file diff --git a/reflection/Reflector.cs b/reflection/Reflector.cs new file mode 100644 index 0000000..3cec26e --- /dev/null +++ b/reflection/Reflector.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +namespace ln.http.resources.reflection +{ + public class Reflector + { + Type TargetType { get; } + + Dictionary properties = new Dictionary(); + Dictionary methods = new Dictionary(); + + public Reflector(Type targetType) + { + TargetType = targetType; + Initialize(); + } + + private void Initialize() + { + foreach (PropertyInfo propertyInfo in TargetType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) + { + if (propertyInfo.GetCustomAttribute() != null) + { + properties.Add(propertyInfo.Name, propertyInfo); + } + } + foreach (MethodInfo methodInfo in TargetType.GetMethods(BindingFlags.Public | BindingFlags.Instance)) + { + if (methodInfo.GetCustomAttribute() != null) + { + methods.Add(methodInfo.Name, methodInfo); + } + } + + } + + public object InvokeRequest(HttpRequest httpRequest,Queue pathStack,object currentValue) + { + if (pathStack.Count == 0) + return currentValue; + + throw new NotImplementedException(); + } + + + + + + static Dictionary reflectorsCache = new Dictionary(); + public static Reflector GetReflector(Type targetType) + { + if (!reflectorsCache.ContainsKey(targetType)) + { + reflectorsCache[targetType] = new Reflector(targetType); + } + return reflectorsCache[targetType]; + } + } +}