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);
                }
            }
        }
Esempio n. 5
0
        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);
        }