static void handleMethods(TextFile tfClass, Type type, GeneratorHelp.ATypeInfo ti, Action <Type> OnNewType) { Action <MethodInfo> action = (method) => { StringBuilder sbDef = new StringBuilder(); bool isI = type.IsInterface; if (!isI) { if (method.IsPublic) { sbDef.Append("public "); } else if (method.IsFamily) { sbDef.Append("protected "); } else if (method.IsAssembly) { sbDef.Append("internal "); } if (method.IsStatic) { sbDef.Append("static "); } sbDef.Append("extern "); if (method.GetBaseDefinition() != method) { sbDef.Append("override "); } else if (!type.IsValueType && method.IsVirtual && !type.IsValueType) { sbDef.Append("virtual "); } } if (!(method.IsSpecialName && method.Name == "op_Implicit")) { sbDef.Append(typefn(method.ReturnType, type.Namespace, CsNameOption.CompilableWithT) + " "); } OnNewType(method.ReturnType); sbDef.Append(MethodNameString(type, method)); if (method.IsGenericMethodDefinition) { Type[] argus = method.GetGenericArguments(); args t_args = new args(); foreach (var a in argus) { t_args.Add(a.Name); } sbDef.Append(t_args.Format(args.ArgsFormat.GenericT)); } sbDef.Append("("); bool hasExtensionAttribute = (method.GetCustomAttributes(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false).Length > 0); ParameterInfo[] ps = method.GetParameters(); { sbDef.Append(Ps2String(type, ps, hasExtensionAttribute)); sbDef.Append(");"); foreach (var p in ps) { OnNewType(p.ParameterType); } } tfClass.Add(sbDef.ToString()); }; bool hasSpecial = false; for (int i = 0; i < ti.Methods.Count; i++) { MemberInfoEx infoEx = ti.Methods[i]; MethodInfo method = infoEx.member as MethodInfo; if (method.IsSpecialName) { hasSpecial = true; action(method); } } if (hasSpecial) { tfClass.AddLine(); } for (int i = 0; i < ti.Methods.Count; i++) { MemberInfoEx infoEx = ti.Methods[i]; MethodInfo method = infoEx.member as MethodInfo; if (!method.IsSpecialName) { action(method); } } }
static void handleInterfaceProblems(TextFile tfClass, Type cType, Action <Type> OnNewType) { Type[] interfaces = cType.GetValidInterfaces(); Action <Type, MethodInfo> actionMethod = (iType, method) => { StringBuilder sbDef = new StringBuilder(); sbDef.Append("extern "); if (!(method.IsSpecialName && method.Name == "op_Implicit")) { sbDef.Append(typefn(method.ReturnType, cType.Namespace, CsNameOption.CompilableWithT) + " "); } OnNewType(method.ReturnType); sbDef.Append(iType.CsFullName(CsNameOption.CompilableWithT) + "."); // 这句是重点 sbDef.Append(MethodNameString(cType, method)); if (method.IsGenericMethodDefinition) { Type[] argus = method.GetGenericArguments(); args t_args = new args(); foreach (var a in argus) { t_args.Add(a.Name); } sbDef.Append(t_args.Format(args.ArgsFormat.GenericT)); } sbDef.Append("("); ParameterInfo[] ps = method.GetParameters(); { sbDef.Append(Ps2String(cType, ps)); sbDef.Append(");"); foreach (var p in ps) { OnNewType(p.ParameterType); } } tfClass.Add(sbDef.ToString()); }; Action <Type, PropertyInfo> actionPro = (iType, pro) => { OnNewType(pro.PropertyType); ParameterInfo[] ps = pro.GetIndexParameters(); args iargs = new args(); bool isIndexer = (ps.Length > 0); if (isIndexer) { for (int j = 0; j < ps.Length; j++) { iargs.AddFormat("{0} {1}", typefn(ps[j].ParameterType, cType.Namespace), ps[j].Name); OnNewType(ps[j].ParameterType); } } MethodInfo getm = pro.GetGetMethod(); MethodInfo setm = pro.GetSetMethod(); bool canGet = getm != null && getm.IsPublic; bool canSet = setm != null && setm.IsPublic; string getset = ""; { if (canGet) { getset += "get;"; } if (canSet) { getset += " set;"; } } string vo = string.Empty; if (isIndexer) { tfClass.Add("extern {4}{0} {1}{2} {{ {3} }}", typefn(pro.PropertyType, cType.Namespace), iType.CsFullName(CsNameOption.CompilableWithT) + ".this", // 这句是重点 iargs.Format(args.ArgsFormat.Indexer), getset, vo); } else { tfClass.Add("extern {3}{0} {1} {{ {2} }}", typefn(pro.PropertyType, cType.Namespace), iType.CsFullName(CsNameOption.CompilableWithT) + "." + // 这句是重点 pro.Name, getset, vo); } }; foreach (Type iType in interfaces) { GeneratorHelp.ATypeInfo ti = GeneratorHelp.CreateTypeInfo(iType); for (int i = 0; i < ti.Methods.Count; i++) { MemberInfoEx infoEx = ti.Methods[i]; MethodInfo method = infoEx.member as MethodInfo; actionMethod(iType, method); } for (int i = 0; i < ti.Pros.Count; i++) { MemberInfoEx infoEx = ti.Pros[i]; PropertyInfo pro = infoEx.member as PropertyInfo; actionPro(iType, pro); } // 特殊处理,BridgeProj工程 if (iType == typeof(ICollection)) { tfClass.Add("bool System.Collections.ICollection.IsReadOnly { get; }"); } } }
public static TextFile GenerateClass() { GeneratorHelp.ATypeInfo ti; int slot = GeneratorHelp.AddTypeInfo(type, out ti); TextFile tfDef = new TextFile(); TextFile tfClass = null; bool gtd = type.IsGenericTypeDefinition; if (!gtd) { tfClass = tfDef.Add("Bridge.define(\"{0}\", {{", JSNameMgr.JsFullName(type)) .In(); tfDef.Add("});"); } else { args TNames = new args(); foreach (var T in type.GetGenericArguments()) { TNames.Add(T.Name); } tfClass = tfDef.Add("Bridge.define(\"{0}\", function ({1}) {{ return {{", JSNameMgr.JsFullName(type), TNames.Format(args.ArgsFormat.OnlyList)) .In(); tfDef.Add("}});"); } // base type, interfaces { Type vBaseType = type.ValidBaseType(); Type[] interfaces = type.GetInterfaces(); if (vBaseType != null || interfaces.Length > 0) { args a = new args(); // 这里baseType要在前面 // Bridge.js: // var noBase = extend ? extend[0].$kind === "interface" : true; // // 可以忽略object基类 // Bridge.js: // if (!extend) { // extend = [Object].concat(interfaces); // } if (vBaseType != null) { a.Add(JSNameMgr.JsFullName(vBaseType)); } foreach (var i in interfaces) { a.Add(JSNameMgr.JsFullName(i)); } tfClass.Add("inherits: [{0}],", a.ToString()); } } if (type.IsInterface) { tfClass.Add("$kind: \"interface\","); } else if (type.IsValueType) { tfClass.Add("$kind: \"struct\","); } TextFile tfStatic = tfClass.Add("statics: {").In(); tfStatic.Out().Add("},"); TextFile tfInst = tfClass.Add(""); if (type.IsValueType) { tfStatic.Add("getDefaultValue: function () {{ return new {0}(); }},", JSNameMgr.JsFullName(type)); tfInst.Add("equals: function (o) {") .In() .Add("if (!Bridge.is(o, {0})) {{", JSNameMgr.JsFullName(type)) .In() .Add("return false;") .BraceOut() .Add(() => { StringBuilder sb = new StringBuilder(); if (ti.Fields.Count == 0) { sb.Append("return true;"); } else { for (int f = 0; f < ti.Fields.Count; f++) { if (ti.Fields[f].Ignored) { continue; } sb.AppendFormat("Bridge.equals(this.{0}, o.{0})", ti.Fields[f].member.Name); if (f < ti.Fields.Count - 1) { sb.AppendFormat(" && "); } else { sb.Append(";"); } } } return(new TextFile().Add(sb.ToString()).Ch); }) .BraceOutComma(); tfInst.Add("$clone: function (to) {") .In() .Add("return this; // don't clone").AddLine() .Add("var s = to || new {0}();", JSNameMgr.JsFullName(type)) .Add(() => { TextFile tf = new TextFile(); for (int f = 0; f < ti.Fields.Count; f++) { if (ti.Fields[f].Ignored) { continue; } tf.Add("s.{0} = this.{0};", ti.Fields[f].member.Name); } return(tf.Ch); }) .Add("return s;") .BraceOutComma(); } BuildConstructors(tfInst, type, ti.Cons, slot); BuildFields(tfStatic, tfInst, type, ti.Fields, slot); BuildProperties(tfStatic, tfInst, type, ti.Pros, slot); BuildMethods(tfStatic, tfInst, type, ti.Methods, slot); return(tfDef); }
static void handlePros(TextFile tfClass, Type type, GeneratorHelp.ATypeInfo ti, Action <Type> OnNewType) { Action <PropertyInfo> action = (pro) => { bool isI = type.IsInterface; OnNewType(pro.PropertyType); ParameterInfo[] ps = pro.GetIndexParameters(); args iargs = new args(); bool isIndexer = (ps.Length > 0); if (isIndexer) { for (int j = 0; j < ps.Length; j++) { iargs.AddFormat("{0} {1}", typefn(ps[j].ParameterType, type.Namespace), ps[j].Name); OnNewType(ps[j].ParameterType); } } MethodInfo getm = pro.GetGetMethod(); MethodInfo setm = pro.GetSetMethod(); bool canGet = getm != null && getm.IsPublic; bool canSet = setm != null && setm.IsPublic; string getset = ""; if (!isI) { if (canGet) { getset += string.Format("get {{ return default({0}); }}", typefn(pro.PropertyType, type.Namespace)); } if (canSet) { getset += " set {}"; } } else { if (canGet) { getset += "get;"; } if (canSet) { getset += " set;"; } } string vo = string.Empty; if (!isI) { vo = "public "; if ((getm != null && getm.IsStatic) || (setm != null && setm.IsStatic)) { vo += "static "; } if (!type.IsValueType) { if ((getm != null && getm.IsVirtual) || (setm != null && setm.IsVirtual)) { vo += ((getm != null && getm.GetBaseDefinition() != getm) || (setm != null && setm.GetBaseDefinition() != setm)) ? "override " : "virtual "; } } } if (isIndexer) { tfClass.Add("{3}{0} this{1} {{ {2} }}", typefn(pro.PropertyType, type.Namespace), iargs.Format(args.ArgsFormat.Indexer), getset, vo); } else { tfClass.Add("{3}{0} {1} {{ {2} }}", typefn(pro.PropertyType, type.Namespace), pro.Name, getset, vo); } }; bool hasNoneIndexer = false; for (int i = 0; i < ti.Pros.Count; i++) { MemberInfoEx infoEx = ti.Pros[i]; PropertyInfo pro = infoEx.member as PropertyInfo; if (pro.GetIndexParameters().Length == 0) { hasNoneIndexer = true; action(pro); } } if (hasNoneIndexer) { tfClass.AddLine(); } for (int i = 0; i < ti.Pros.Count; i++) { MemberInfoEx infoEx = ti.Pros[i]; PropertyInfo pro = infoEx.member as PropertyInfo; if (pro.GetIndexParameters().Length > 0) { action(pro); } } }
public static TextFile Build_DelegateFunction(Type classType, MemberInfo memberInfo, Type delType, int methodTag, int argIndex) { // building a closure // a function having a up-value: jsFunction string getDelFunctionName = GetMethodArg_DelegateFuncionName(classType, memberInfo.Name, methodTag, argIndex); TextFile tf = new TextFile(); MethodInfo delInvoke = delType.GetMethod("Invoke"); ParameterInfo[] ps = delInvoke.GetParameters(); Type returnType = delType.GetMethod("Invoke").ReturnType; var argsParam = new args(); for (int i = 0; i < ps.Length; i++) { argsParam.Add(ps[i].Name); } // format as <t,u,v> string stringTOfMethod = string.Empty; if (delType.ContainsGenericParameters) { var arg = new args(); foreach (var t in delType.GetGenericArguments()) { arg.Add(t.Name); } stringTOfMethod = arg.Format(args.ArgsFormat.GenericT); } // this function name is used in BuildFields, don't change TextFile tfFun = tf.Add("public static {0} {1}{2}(CSRepresentedObject objFunction)", JSNameMgr.CsFullName(delType, CsNameOption.CompilableWithT), // [0] getDelFunctionName, // [2] stringTOfMethod // [1] ) .BraceIn(); { tfFun.Add("if (objFunction == null || objFunction.jsObjID == 0)") .In() .Add("return null;") .Out() .AddLine(); tfFun.Add("{0} action = JSMgr.getJSFunCSDelegateRel<{0}>(objFunction.jsObjID);", JSNameMgr.CsFullName(delType, CsNameOption.CompilableWithT)); tfFun.Add("if (action != null)") .In() .Add("return action;") .Out() .AddLine(); TextFile tfAction = tfFun.Add("action = ({0}) => ", argsParam.Format(args.ArgsFormat.OnlyList)) .BraceIn(); { tfAction.Add("JSMgr.vCall.CallJSFunctionValue(0, objFunction.jsObjID{0}{1});", (argsParam.Count > 0) ? ", " : "", argsParam); if (returnType != typeof(void)) { tfAction.Add("return (" + JSNameMgr.CsFullName(returnType) + ")" + JSDataExchangeEditor.Get_GetJSReturn(returnType) + ";"); } tfAction.BraceOutSC(); } tfFun.Add("JSMgr.addJSFunCSDelegateRel(objFunction.jsObjID, action);") .Add("return action;\n"); tfFun.BraceOut(); } return(tf); }