123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770 |
- using Edge.Core.Processor.Communicator;
- using Edge.Core.Processor.Dispatcher;
- using Edge.Core.Processor.Dispatcher.Attributes;
- using Edge.Core.UniversalApi;
- using Newtonsoft.Json.Linq;
- using Newtonsoft.Json.Schema;
- using Newtonsoft.Json.Schema.Generation;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics.CodeAnalysis;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Text.Json;
- using System.Text.Json.Serialization;
- using System.Threading.Tasks;
- namespace Edge.Core.Processor
- {
- public enum ProcessorType
- {
-
-
-
- DeviceProcessor,
-
-
-
- Application
- }
- public class ProcessorDescriptor
- {
- public IProcessor Processor { get; }
-
-
-
- public ProcessorType ProcessorType { get; }
-
-
-
-
- public object DeviceHandlerOrApp { get; }
-
-
-
- public IEnumerable<UniversalApiInfo> UniversalApiInfos { get; }
-
-
-
- public object DeviceProcessorContext { get; }
-
-
-
- public object DeviceProcessorCommunicator { get; }
- public ProcessorDescriptor(IProcessor processor, ProcessorType processorType,
- object deviceHandlerOrApp,
- IEnumerable<UniversalApiInfo> universalApiInfos,
- object deviceProcessorContext,
- object deviceProcessorCommunicator)
- {
- this.Processor = processor;
- this.ProcessorType = processorType;
- this.DeviceProcessorContext = deviceProcessorContext;
- this.DeviceProcessorCommunicator = deviceProcessorCommunicator;
- this.DeviceHandlerOrApp = deviceHandlerOrApp;
- this.UniversalApiInfos = universalApiInfos;
- }
- }
- public class UniversalEventInfo
- {
- public UniversalEventInfo(string eventName, Type eventDataType)
- {
- this.EventName = eventName;
- this.EventDataType = eventDataType;
- }
- public string EventName { get; private set; }
- public Type EventDataType { get; private set; }
- }
- public class UniversalApiInfo
- {
- public IProcessor Processor { get; set; }
- public UniversalApiInfo(MethodInfo serviceApiInfo, UniversalApiAttribute apiAttribute)
- {
- this.ServiceApiInfo = serviceApiInfo;
- this.ApiAttribute = apiAttribute;
- }
- public UniversalApiInfo(PropertyInfo propertyApiInfo, UniversalApiAttribute apiAttribute)
- {
- this.PropertyApiInfo = propertyApiInfo;
- this.ApiAttribute = apiAttribute;
- }
- public UniversalApiInfo(UniversalEventInfo eventApiInfo, UniversalApiAttribute apiAttribute)
- {
- this.EventApiInfo = eventApiInfo;
- this.ApiAttribute = apiAttribute;
- }
-
-
- public MethodInfo ServiceApiInfo { get; private set; }
- public PropertyInfo PropertyApiInfo { get; private set; }
- public UniversalEventInfo EventApiInfo { get; private set; }
-
-
- public UniversalApiAttribute ApiAttribute { get; private set; }
- }
- public class UniversalApiInfoDoc
- {
-
-
-
- public string ProviderType { get; set; }
- public string[] ProviderTags { get; set; }
-
-
-
- public string ProviderConfigName { get; set; }
-
-
-
- public string BaseCategory { get; set; }
-
-
-
- public string ApiName { get; set; }
-
-
-
- public string Path { get; set; }
- public string InputParametersExampleJson { get; set; }
-
-
-
- public string[] InputParametersJsonSchemaStrings { get; set; }
- public string OutputParametersExampleJson { get; set; }
- public string OutputParametersJsonSchema { get; set; }
- public string Description { get; set; }
- }
- public static class ExtensionMethods
- {
-
-
-
-
-
- public static ProcessorDescriptor ProcessorDescriptor(this IProcessor processor)
- {
- if (processor == null)
- throw new ArgumentNullException(nameof(processor));
- if (processor is IAppProcessor application)
- {
- var apiInfos = GetUniversalApiInfos(application.GetType(), processor);
- return new ProcessorDescriptor(processor,
- ProcessorType.Application, processor, apiInfos, null, null);
- }
- else
- {
- dynamic p = processor;
- var deviceProcessorHandler = p.Context.Handler;
- Type handlerType = deviceProcessorHandler.GetType();
- var methodInfos = GetUniversalApiInfos(handlerType, processor);
- return new ProcessorDescriptor(processor,
- ProcessorType.DeviceProcessor,
- deviceProcessorHandler, methodInfos, p.Context, p.Context.Communicator);
- }
- }
- private static IEnumerable<UniversalApiInfo> GetUniversalApiInfos(Type handlerOrAppType, IProcessor processor)
- {
- var serviceUniversalApiInfos = handlerOrAppType.GetMethods()
- .Where(m =>
- m.CustomAttributes != null
- && m.CustomAttributes.Any(a => a.AttributeType
- .IsAssignableFrom(typeof(UniversalApiAttribute)))
- && m.GetCustomAttribute<UniversalApiAttribute>().IgnoreApi == false
- && typeof(Task).IsAssignableFrom(m.ReturnType))
- .Select(mi => new UniversalApiInfo(mi, mi.GetCustomAttributes<UniversalApiAttribute>().First())
- {
- Processor = processor
- });
- var eventUniversalApiAttributes = handlerOrAppType
- .GetCustomAttributes<UniversalApiAttribute>().Where(att => att.IgnoreApi == false);
- if (eventUniversalApiAttributes.Any()
- && eventUniversalApiAttributes.GroupBy(g => g.Name).Any(g => g.Count() >= 2))
- throw new ArgumentOutOfRangeException("Multiple event UniversalApiAttributes with same Name: " +
- (eventUniversalApiAttributes.GroupBy(g => g.Name).Where(g => g.Count() >= 2).First().Key ?? "")
- + " declared on type: " + handlerOrAppType.FullName + ", make sure the event name is unique on this type.");
- var eventUniversalApiInfos = eventUniversalApiAttributes.Select(atti =>
- new UniversalApiInfo(new UniversalEventInfo(atti.Name, atti.EventDataType), atti)
- {
- Processor = processor
- });
- var propertyUniversalApiInfos = handlerOrAppType.GetProperties()
- .Where(p =>
- p.CustomAttributes != null
- && p.CustomAttributes.Any(a => a.AttributeType
- .IsAssignableFrom(typeof(UniversalApiAttribute)))
- && p.GetCustomAttribute<UniversalApiAttribute>().IgnoreApi == false)
- .Select(p => new UniversalApiInfo(p, p.GetCustomAttributes<UniversalApiAttribute>().First())
- {
- Processor = processor
- });
- var apiInfos = serviceUniversalApiInfos.Concat(eventUniversalApiInfos).Concat(propertyUniversalApiInfos);
- return apiInfos;
- }
-
-
-
-
-
-
- public static IEnumerable<IProcessor> WithHandlerOrApp<T>(this IEnumerable<IProcessor> processors) where T : class
- {
- if (processors == null) throw new ArgumentNullException(nameof(processors));
- return processors.Where(p => p.IsWithHandlerOrApp<T>());
- }
-
-
-
-
-
-
- public static bool IsWithHandlerOrApp<T>(this IProcessor processor) where T : class
- {
- if (processor == null) throw new ArgumentNullException(nameof(processor));
- var endpointType = processor.ProcessorDescriptor()?.DeviceHandlerOrApp?.GetType();
- if (endpointType == null) return false;
- return endpointType.IsAssignableFrom(typeof(T)) || typeof(T).IsAssignableFrom(endpointType);
- }
-
-
-
-
-
-
- public static IEnumerable<T> SelectHandlerOrAppThenCast<T>(this IEnumerable<IProcessor> processors) where T : class
- {
- if (processors == null) throw new ArgumentNullException(nameof(processors));
- return processors.Select(p => p.SelectHandlerOrAppThenCast<T>());
- }
-
-
-
-
-
-
- public static T SelectHandlerOrAppThenCast<T>(this IProcessor processor) where T : class
- {
- if (processor == null) throw new ArgumentNullException(nameof(processor));
- var casted = processor.ProcessorDescriptor().DeviceHandlerOrApp as T;
- if (casted == null) throw new InvalidCastException();
- return casted;
- }
- public static IEnumerable<MethodBase> WithAttributeOrAll<T>(this IEnumerable<MethodBase> methodsOrCtors) where T : Attribute
- {
- var memberInfoWithAttri = methodsOrCtors.Where(mi => mi.GetCustomAttribute<T>() != null);
- if (memberInfoWithAttri.Any()) return memberInfoWithAttri;
- return methodsOrCtors;
- }
- public static IEnumerable<UniversalApiInfoDoc> FilterByTags(this IEnumerable<UniversalApiInfoDoc> source, string[] tags)
- {
- if (source == null) throw new ArgumentNullException(nameof(source));
- if (tags == null || !tags.Any() || tags.All(t => string.IsNullOrEmpty(t)))
- return source;
- else
- {
- return source.Where(d => d.ProviderTags != null && d.ProviderTags.Any()).Where(doc => tags.Intersect(doc.ProviderTags).Any());
-
-
-
-
-
-
-
- }
- }
- public static IEnumerable<ProcessorMetaDescriptor> ExtractProcessorMetaDescriptor(
- this IEnumerable<Type> targetEndPointTypes, bool includeSystemInternalComponent = false)
- {
- var descriptors = new List<ProcessorMetaDescriptor>();
- foreach (var endPointType in targetEndPointTypes)
- {
- var endpointTypeMetaPartsDescriptor = endPointType.GetCustomAttributes<MetaPartsDescriptor>().FirstOrDefault();
- if ((endpointTypeMetaPartsDescriptor?.IsSystemInternalComponent ?? false) && !includeSystemInternalComponent) continue;
- var pmcDescriptor = new ProcessorMetaDescriptor
- {
-
-
- Type = endPointType.GetInterfaces().Any(ti => ti.Name == typeof(IAppProcessor).Name) ?
- ProcessorTypeEnum.AppProcessor : ProcessorTypeEnum.DeviceProcessor,
- SourceEndpointFullTypeStr = endPointType.AssemblyQualifiedName,
- Tags = endpointTypeMetaPartsDescriptor?.Tags,
- DisplayName = endpointTypeMetaPartsDescriptor?.DisplayName,
- Description = endpointTypeMetaPartsDescriptor?.Description
- };
- if (pmcDescriptor.Type == ProcessorTypeEnum.AppProcessor)
- {
-
- pmcDescriptor.MetaPartsGroupDescriptors = new List<ProcessorMetaPartsGroupDescriptor>() {
- new ProcessorMetaPartsGroupDescriptor()
- {
- GroupType = ProcessorMetaPartsTypeEnum.App,
- MetaPartsDescriptors = new List<ProcessorMetaPartsDescriptor>()
- {
- new ProcessorMetaPartsDescriptor() {
- FullTypeString = endPointType.AssemblyQualifiedName,
- TypeString = endPointType.FullName,
- DisplayName = endPointType.GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- endPointType.GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- endPointType.GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- }
- }
- }
- };
- }
- else
- {
- var groupDescriptors = new List<ProcessorMetaPartsGroupDescriptor>();
- var deviceHandlerGroupDescriptor =
- new ProcessorMetaPartsGroupDescriptor()
- {
- GroupType = ProcessorMetaPartsTypeEnum.DeviceHandler,
- MetaPartsDescriptors = new List<ProcessorMetaPartsDescriptor>()
- {
- new ProcessorMetaPartsDescriptor() {
- FullTypeString = endPointType.AssemblyQualifiedName,
- TypeString = endPointType.FullName,
- DisplayName = endPointType.GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- endPointType.GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- endPointType.GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- }
- }
- };
- groupDescriptors.Add(deviceHandlerGroupDescriptor);
- var metaPartsRequiredAttributes = endPointType.GetCustomAttributes<MetaPartsRequired>();
- var communicatorMetaPartsRequiredAttributes = metaPartsRequiredAttributes?.Where(at => at.RequiredPartsType?.GetInterfaces().Any(i => i.Name == typeof(ICommunicator<,>).Name) ?? false);
- if (communicatorMetaPartsRequiredAttributes == null || !communicatorMetaPartsRequiredAttributes.Any())
- {
- var communicatorGroupDescriptor = new ProcessorMetaPartsGroupDescriptor()
- {
- GroupType = ProcessorMetaPartsTypeEnum.Communicator,
- MetaPartsDescriptors = new List<ProcessorMetaPartsDescriptor>(){
- new ProcessorMetaPartsDescriptor()
- {
- FullTypeString = typeof(ComPortCommunicator<>).AssemblyQualifiedName,
- TypeString = typeof(ComPortCommunicator<>).FullName,
- DisplayName = typeof(ComPortCommunicator<>).GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- typeof(ComPortCommunicator<>).GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- typeof(ComPortCommunicator<>).GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- },
- new ProcessorMetaPartsDescriptor()
- {
- FullTypeString = typeof(TcpClientCommunicator<>).AssemblyQualifiedName,
- TypeString = typeof(TcpClientCommunicator<>).FullName,
- DisplayName = typeof(TcpClientCommunicator<>).GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- typeof(TcpClientCommunicator<>).GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- typeof(TcpClientCommunicator<>).GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- },
- new ProcessorMetaPartsDescriptor()
- {
- FullTypeString = typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator<>).AssemblyQualifiedName,
- TypeString = typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator<>).FullName,
- DisplayName =typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator<>).GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator<>).GetCustomAttribute<MetaPartsRequired>() == null ? "" : typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator<>).GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator<>).GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- },
- new ProcessorMetaPartsDescriptor()
- {
- FullTypeString = typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator_Silent<>).AssemblyQualifiedName,
- TypeString = typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator_Silent<>).FullName,
- DisplayName =typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator_Silent<>).GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator_Silent<>).GetCustomAttribute<MetaPartsRequired>() == null ? "" : typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator_Silent<>).GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- typeof(HengShan_TQC_IFsfMessageTcpIpCommunicator_Silent<>).GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- }
- }
- };
- groupDescriptors.Add(communicatorGroupDescriptor);
- }
- else
- {
- groupDescriptors.Add(new ProcessorMetaPartsGroupDescriptor()
- {
- GroupType = ProcessorMetaPartsTypeEnum.Communicator,
- MetaPartsDescriptors = communicatorMetaPartsRequiredAttributes.Select(att =>
- new ProcessorMetaPartsDescriptor()
- {
- FullTypeString = att.RequiredPartsType.AssemblyQualifiedName,
- TypeString = att.RequiredPartsType.FullName,
- DisplayName = att.RequiredPartsType.GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- att.RequiredPartsType.GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- att.RequiredPartsType.GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor => ctor.ResolveParamsJsonSchemas()).ToList(),
- }).ToArray()
- });
- }
- var deviceProcessorMetaPartsRequiredAttri = metaPartsRequiredAttributes?.FirstOrDefault(at => at.RequiredPartsType?.GetInterfaces().Any(i => i.Name == typeof(IDeviceProcessor<,>).Name) ?? false);
- if (deviceProcessorMetaPartsRequiredAttri != null)
- {
- var specifiedProcessorGroupDescriptor = new ProcessorMetaPartsGroupDescriptor()
- {
- GroupType = ProcessorMetaPartsTypeEnum.DeviceProcessor,
- MetaPartsDescriptors = new List<ProcessorMetaPartsDescriptor>(){
- new ProcessorMetaPartsDescriptor()
- {
- FullTypeString = deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.AssemblyQualifiedName,
- TypeString = deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.FullName,
- DisplayName = deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- } }
- };
- groupDescriptors.Add(specifiedProcessorGroupDescriptor);
- }
- else
- {
- var processorGroupDescriptor = new ProcessorMetaPartsGroupDescriptor()
- {
- GroupType = ProcessorMetaPartsTypeEnum.DeviceProcessor,
- MetaPartsDescriptors = new List<ProcessorMetaPartsDescriptor>(){
- new ProcessorMetaPartsDescriptor()
- {
- FullTypeString = typeof(GenericDeviceProcessor<,>).AssemblyQualifiedName,
- TypeString= typeof(GenericDeviceProcessor<,>).FullName,
- DisplayName = typeof(GenericDeviceProcessor<,>).GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- typeof(GenericDeviceProcessor<,>).GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- typeof(GenericDeviceProcessor<,>).GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- },
- new ProcessorMetaPartsDescriptor()
- {
- FullTypeString = typeof(HalfDuplexActivePollingDeviceProcessor<,>).AssemblyQualifiedName,
- TypeString= typeof(HalfDuplexActivePollingDeviceProcessor<,>).FullName,
- DisplayName = typeof(HalfDuplexActivePollingDeviceProcessor<,>).GetCustomAttribute<MetaPartsDescriptor>()?.DisplayName,
- Description =
- typeof(HalfDuplexActivePollingDeviceProcessor<,>).GetCustomAttribute<MetaPartsDescriptor>()?.Description,
- ParametersJsonSchemaStrings =
- typeof(HalfDuplexActivePollingDeviceProcessor<,>).GetConstructors().WithAttributeOrAll<ParamsJsonSchemas>().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(),
- }
- }
- };
- groupDescriptors.Add(processorGroupDescriptor);
- }
- pmcDescriptor.MetaPartsGroupDescriptors = groupDescriptors;
- }
- descriptors.Add(pmcDescriptor);
- }
- return descriptors;
- }
-
-
-
-
-
-
- public static bool TryCallMetaPartsConfigCompatibilityMethodAndUpdate(this ProcessorMetaPartsConfig metaPartsConfig)
- {
- var metaPartsType = Type.GetType(metaPartsConfig.FullTypeString);
- if (metaPartsType == null) return false;
- string methodName = "ResolveCtorMetaPartsConfigCompatibility";
- var resolveCompatibleMethodInfo =
- metaPartsType.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)
- .Where(mi => mi.Name == methodName
- && mi.ReturnType == typeof(List<object>)).FirstOrDefault();
- if (resolveCompatibleMethodInfo == null)
- {
-
- return false;
- }
- else
- {
- try
- {
- var reformatParams = resolveCompatibleMethodInfo.Invoke(null,
- new object[] { metaPartsConfig.ParametersJsonArrayStr }
- ) as List<object>;
- var jsonSerializerOptions = new JsonSerializerOptions()
- {
- WriteIndented = true,
- PropertyNameCaseInsensitive = true,
- };
- jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
- var reformatParamsStr = "[" + reformatParams.Select(p => JsonSerializer.Serialize(p)).Aggregate((acc, n) => acc + ", " + n) + "]";
- metaPartsConfig.ParametersJsonArrayStr = reformatParamsStr;
- return true;
- }
- catch { return false; }
- }
- }
- public static List<string> ResolveParamsJsonSchemas(this MethodBase methodOrCtor)
- {
- Type declaringType = methodOrCtor.DeclaringType;
- var apiDesc = methodOrCtor.GetCustomAttribute<ParamsJsonSchemas>();
- if (apiDesc != null)
- {
- if (!string.IsNullOrEmpty(apiDesc.SchemaEmbededResourceName))
- {
- var resourceName = declaringType.Assembly.GetManifestResourceNames().FirstOrDefault(n => n.EndsWith("." + apiDesc.SchemaEmbededResourceName));
- if (resourceName != null)
- {
- var resourceStream = declaringType.Assembly.GetManifestResourceStream(resourceName);
- if (resourceStream != null)
- using (var sr = new StreamReader(resourceStream))
- {
- var content = sr.ReadToEnd();
- try
- {
- var jsonSchemaRootElement = JsonDocument.Parse(content).RootElement;
- if (jsonSchemaRootElement.ValueKind == JsonValueKind.Array)
- return jsonSchemaRootElement.EnumerateArray().Select(jse => jse.GetRawText()).ToList();
- return new List<string>() { content };
- }
- catch (Exception exxx) { }
- }
- }
- }
- if (apiDesc.SchemaStrings != null && apiDesc.SchemaStrings.Any()
- && apiDesc.SchemaStrings.Length ==
- methodOrCtor.GetParameters().Where(p =>
- !p.ParameterType.IsInterface && !p.ParameterType.IsAbstract).Count())
- return apiDesc.SchemaStrings.ToList();
- }
- var generator = new JSchemaGenerator();
- generator.GenerationProviders.Add(new StringEnumGenerationProvider());
- return methodOrCtor.GetParameters().Where(p => !p.ParameterType.IsInterface && !p.ParameterType.IsAbstract)
- .Select(p =>
- {
- int serializeDepth = 0;
- if (IsTypeDepthTooHighForSerialize(p.ParameterType, ref serializeDepth))
- return "{}".Insert(1, "\"title\": \"" + p.Name + " ----> of type: " + p.ParameterType.Name + " 's Depth is Too High for Serialize and Generate Json Sample, try avoid recursive properties\", \"type\": \"object\"");
- else
- return generator.Generate(p.ParameterType).ToString().Insert(1, "\"title\": \"" + p.Name + "\",");
- }).ToList();
- }
-
-
-
-
-
-
- private static bool IsTypeDepthTooHighForSerialize(Type targetType, ref int depth)
- {
- var targetProperties = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.PropertyType.IsClass && !p.PropertyType.IsPrimitive);
- foreach (var p in targetProperties)
- {
- depth++;
- if (depth >= 64) return true;
- if (IsTypeDepthTooHighForSerialize(p.PropertyType, ref depth))
- return true;
- else
- continue;
- }
- return false;
- }
- public static string ResolveParamsJsonSchemas(this PropertyInfo propertyInfo)
- {
- Type declaringType = propertyInfo.PropertyType;
- var generator = new JSchemaGenerator();
- generator.GenerationProviders.Add(new StringEnumGenerationProvider());
- return generator.Generate(declaringType).ToString();
- }
- public static string ResolveParamsJsonSchema(this Type type)
- {
- var generator = new JSchemaGenerator();
- generator.GenerationProviders.Add(new StringEnumGenerationProvider());
- return generator.Generate(type).ToString();
- }
-
-
-
-
-
- public static JToken GenerateJsonSample(this JSchema schema)
- {
- JToken output;
- switch (schema.Type)
- {
- case JSchemaType.Object:
- var jObject = new JObject();
- if (schema.Properties != null)
- {
- foreach (var prop in schema.Properties)
- {
- jObject.Add(LowerCaseFirstChar(prop.Key), GenerateJsonSample(prop.Value));
- }
- }
- output = jObject;
- break;
- case JSchemaType.Object | JSchemaType.Null:
- var jObject2 = new JObject();
- if (schema.Properties != null)
- {
- foreach (var prop in schema.Properties)
- {
- jObject2.Add(LowerCaseFirstChar(prop.Key), GenerateJsonSample(prop.Value));
- }
- }
- output = jObject2;
- break;
- case JSchemaType.Array:
- var jArray = new JArray();
- foreach (var item in schema.Items)
- {
- jArray.Add(GenerateJsonSample(item));
- }
- output = jArray;
- break;
- case JSchemaType.Array | JSchemaType.Null:
- var jArray2 = new JArray();
- foreach (var item in schema.Items)
- {
- jArray2.Add(GenerateJsonSample(item));
- }
- output = jArray2;
- break;
- case JSchemaType.String:
- if (schema.Format == "date-time")
- output = new JValue("2020-04-01T00:01:02.8514872+08:00");
- else if (schema.Enum != null && schema.Enum.Any())
- {
- if (string.IsNullOrEmpty(schema.Enum.First().ToString()))
- {
- if (schema.Enum.Count >= 2)
- output = new JValue(schema.Enum[1].ToString());
- else
- output = Newtonsoft.Json.Linq.JValue.CreateNull();
- }
- else
- output = new JValue(schema.Enum.First().ToString());
- }
- else
- output = new JValue("string_sample");
- break;
- case JSchemaType.String | JSchemaType.Null:
- if (schema.Format == "date-time")
- output = new JValue("2020-04-01T00:01:02.8514872+08:00");
- else if (schema.Enum != null && schema.Enum.Any())
- {
- if (string.IsNullOrEmpty(schema.Enum.First().ToString()))
- {
- if (schema.Enum.Count >= 2)
- output = new JValue(schema.Enum[1].ToString());
- else
- output = JValue.CreateNull();
- }
- else
- output = new JValue(schema.Enum.First().ToString());
- }
- else
- output = new JValue("nullable_string_sample");
- break;
- case JSchemaType.Number:
- output = new JValue(1.0);
- break;
- case JSchemaType.Integer:
- output = new JValue(1);
- break;
- case JSchemaType.Boolean:
- output = new JValue(false);
- break;
- case JSchemaType.Null:
- output = JValue.CreateNull();
- break;
-
- case Newtonsoft.Json.Schema.JSchemaType.String | Newtonsoft.Json.Schema.JSchemaType.Number | Newtonsoft.Json.Schema.JSchemaType.Integer | Newtonsoft.Json.Schema.JSchemaType.Boolean | Newtonsoft.Json.Schema.JSchemaType.Object | Newtonsoft.Json.Schema.JSchemaType.Array:
- output = JValue.CreateNull();
- break;
- default:
- output = null;
- break;
- }
- return output;
- }
- private static string LowerCaseFirstChar(string name)
- {
- return name.Substring(0, 1).ToLower() + name.Substring(1);
- }
- public static string GenerateParametersJsonSample(this string[] parametersJsonSchemaStrings)
- {
- if (parametersJsonSchemaStrings == null || !parametersJsonSchemaStrings.Any()) return "[]";
- var jTokens = parametersJsonSchemaStrings.Select(s => JSchema.Parse(s)).Select(js => js.GenerateJsonSample());
- return "[" + jTokens.Select(jt => jt.Type == JTokenType.String ? "\"" + jt.ToString() + "\"" : jt.ToString()).Aggregate((acc, n) => acc + ", " + n) + "]";
- }
- public static string GenerateParameterJsonSample(this string parameterJsonSchemaString)
- {
- if (string.IsNullOrEmpty(parameterJsonSchemaString)) return "";
- var jToken = JSchema.Parse(parameterJsonSchemaString).GenerateJsonSample();
- return jToken.ToString();
- }
- }
- }
|