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 { namespace Attr { [AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)] public class SerializeAttribute : Attribute { public string Description { get; set; } } [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public sealed class MethodAttribute : SerializeAttribute { } [System.AttributeUsage(AttributeTargets.Enum, Inherited = true, AllowMultiple = false)] public sealed class EnumAttribute : SerializeAttribute { } } public abstract class RScriptInjectVariable { public string RScriptString { get; private set; } protected abstract string WritePageHead(Type currentType); #region Enum protected abstract string WriteEnumHead(Type currentEnum); protected abstract string WriteEnumBodyEnter(Type currentType); protected abstract string WriteEnumName(string enumName, Type valueType); protected abstract string WriteEnumBodyExit(Type currentType); protected abstract string WriteEnumTail(Type currentType); #endregion #region Class 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); #endregion protected abstract string WritePageEnd(Type currentType); /// /// 生成targetType类型的实体 /// /// public delegate object Generater(); private Generater MyGenerater; public readonly static Dictionary AllRScriptInjectVariables = new(); public readonly string name; public readonly string script; public object Generate() { return MyGenerater(); } public RScriptInjectVariable(Type targetType, [MaybeNull]Generater generater, string name) { if (AllRScriptInjectVariables.ContainsKey(name)) throw new InvalidOperationException($"{name} is been used"); { StringBuilder builder = new(); builder.AppendLine(this.WritePageHead(targetType)); builder.AppendLine(this.WriteClassHead(targetType)); builder.AppendLine(this.WriteClassBodyEnter(targetType)); // 绘制枚举 { var scriptEnums = from enumItem in targetType.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Public) where enumItem.GetCustomAttribute() != null select enumItem; foreach (var enumItem in scriptEnums) { var attr = enumItem.GetCustomAttribute(); } } // 绘制方法 { var scriptMethods = from method in targetType.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(targetType)); builder.AppendLine(this.WriteClassTail(targetType)); builder.AppendLine(this.WritePageEnd(targetType)); this.script = builder.ToString(); } 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"); } } }