123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- using Newtonsoft.Json;
- using System;
- using System.IO;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- using VCommon.Json;
- using VCommon.Logging;
- using VCommon.VOpenApi.Json;
- namespace VCommon.VOpenApi
- {
- public class ApiBind
- {
- private static readonly JsonReturnValueSerializer ReturnValueSerializer = new JsonReturnValueSerializer();
- private readonly Type _interfaceType;
- private readonly Func<object, object, object> _preCompiledInvoke;
- public string RawRoute { get; }
- public Type ApiResourceType { get; }
- public MethodInfo ApiMethod { get; }
- public Type InputParamType { get; }
- public string ResourceName { get; }
- public string Name { get; }
- public ApiBind(MethodInfo apiMethod, string resourceName, string name, Type interfaceType, string rawRoute)
- {
- _interfaceType = interfaceType;
- ApiMethod = apiMethod;
- ResourceName = resourceName;
- Name = name;
- ApiResourceType = apiMethod.DeclaringType;
- var parameters = ApiMethod.GetParameters();
- if (1 == parameters.Length)
- {
- InputParamType = parameters[0].ParameterType;
- }
- RawRoute = rawRoute;
- //Compile method invoke reduce time
- {
- var hasParam = InputParamType != null;
- var hasReturn = apiMethod.ReturnType != typeof(void);
- var pInstance = Expression.Parameter(typeof(object), "instance");
- var unboxInstance = Expression.Convert(pInstance, interfaceType);
- var pInput = Expression.Parameter(typeof(object), "input");
- MethodCallExpression invoke;
- if (hasParam)
- {
- var unboxInput = Expression.Convert(pInput, InputParamType);
- invoke = Expression.Call(unboxInstance, apiMethod, unboxInput);
- }
- else
- {
- invoke = Expression.Call(unboxInstance, apiMethod);
- }
- if (hasParam)
- {
- if (hasReturn)
- {
- var cvr = Expression.Convert(invoke, typeof(object));
- var lam = Expression.Lambda<Func<object, object, object>>(cvr, pInstance, pInput);
- _preCompiledInvoke = lam.Compile();
- }
- else
- {
- var lam = Expression.Lambda<Action<object, object>>(invoke, pInstance, pInput);
- var del = lam.Compile();
- _preCompiledInvoke = (instance, input) =>
- {
- del(instance, input);
- return null;
- };
- }
- }
- else
- {
- if (hasReturn)
- {
- var cvr = Expression.Convert(invoke, typeof(object));
- var lam = Expression.Lambda<Func<object, object>>(cvr, pInstance);
- var del = lam.Compile();
- _preCompiledInvoke = (instance, _) => del(instance);
- }
- else
- {
- var lam = Expression.Lambda<Action<object>>(invoke, pInstance);
- var del = lam.Compile();
- _preCompiledInvoke = (instance, _) =>
- {
- del(instance);
- return null;
- };
- }
- }
- }
- }
- public async Task Invoke(Func<Type, object> resolveFunc, Stream inputStream, Stream outputStream)
- {
- object inputParam = null;
- if (null != InputParamType)
- {
- //TODO: PACT? Scheme check?
- var inputReader = new StreamReader(inputStream, Encoding.UTF8);
- var input = await inputReader.ReadToEndAsync();
- try
- {
- inputParam = VJsonSerializer.Deserialize(input, InputParamType);
- }
- catch (JsonReaderException exception)
- {
- throw new VApiArgumentException("参数错误:" + exception.Message);
- }
- catch (JsonSerializationException exception)
- {
- throw new VApiArgumentException($"参数错误:{exception.Message}{exception.InnerException?.Message}");
- }
- catch (Exception exception)
- {
- Logger.Error("ApiBind: Error on parsing input", new { inputJson = input, exception });
- throw new VApiArgumentException("参数错误");
- }
- }
- var inst = resolveFunc(_interfaceType);
- var returnValue = _preCompiledInvoke(inst, inputParam);
- var output = ReturnValueSerializer.SerializeObject(returnValue);
- var bufOutput = Encoding.UTF8.GetBytes(output);
- await outputStream.WriteAsync(bufOutput, 0, bufOutput.Length);
- }
- }
- }
|