using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Convention.RScript.Variable { [System.AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public sealed class RScriptMethodAttribute : Attribute { public string Description { get; set; } } public abstract class RScriptInjectVariable { public string RScriptString { get; private set; } protected abstract string WriteClassHead(Type currentType); protected abstract string WriteClassBodyEnter(Type currentType); protected abstract string WriteClassMethod(Type returnType, string methodName, string[] parameterNames, Type[] parameterTypes, string description); protected abstract string WriteClassBodyExit(Type currentType); protected abstract string WriteClassTail(Type currentType); public delegate object Generater(); private Generater MyGenerater; public string name { get; private set; } public object Generate() { return MyGenerater(); } public RScriptInjectVariable([MaybeNull]Generater generater, string name) { var currentType = this.GetType(); StringBuilder builder = new(); builder.AppendLine(this.WriteClassHead(currentType)); builder.AppendLine(this.WriteClassBodyEnter(currentType)); var scriptMethods = from method in currentType.GetMethods(BindingFlags.Instance | BindingFlags.Public) where method.GetCustomAttribute() != null select method; foreach (var method in scriptMethods) { var attr = method.GetCustomAttribute(); var returnType = method.ReturnType; var methodName = method.Name; var parameters = method.GetParameters(); var parameterNames = from item in parameters select item.Name; var parameterTypes = from item in parameters select item.ParameterType; builder.AppendLine(this.WriteClassMethod(returnType, methodName, parameterNames.ToArray(), parameterTypes.ToArray(), attr.Description)); } builder.AppendLine(this.WriteClassBodyExit(currentType)); builder.AppendLine(this.WriteClassTail(currentType)); this.MyGenerater = generater; this.name = name; } public static object GenerateRScriptVariable(string name, Dictionary classes) { if (classes.TryGetValue(name, out var variable)) { if (variable.MyGenerater != null) return variable.Generate(); } throw new InvalidOperationException($"{name} target is not exist or abstract"); } } }