public static void BuildFields(TextFile tfStatic, TextFile tfInst,
                                       Type type, List <MemberInfoEx> fields, int slot)
        {
            TextFile tfStatic2 = null, tfInst2 = null;

            for (int i = 0; i < fields.Count; i++)
            {
                MemberInfoEx infoEx = fields[i];
                if (infoEx.Ignored)
                {
                    continue;
                }
                FieldInfo field = infoEx.member as FieldInfo;
                if (field.IsStatic)
                {
                    if (tfStatic2 == null)
                    {
                        tfStatic2 = tfStatic.Add("$fields: {").In();
                        tfStatic2.Out().Add("},");
                    }
                }
                else
                {
                    if (tfInst2 == null)
                    {
                        tfInst2 = tfInst.Add("$fields: {").In();
                        tfInst2.Out().Add("},");
                    }
                }
            }

            for (int i = 0; i < fields.Count; i++)
            {
                MemberInfoEx infoEx = fields[i];
                if (infoEx.Ignored)
                {
                    continue;
                }
                FieldInfo field = infoEx.member as FieldInfo;

                TextFile tf = field.IsStatic ? tfStatic2 : tfInst2;
                tf.Add("{0}: {{", field.Name).In()
                .Add("get: function () {{ return CS.Call({0}, {1}, {2}, {3}{4}); }},", (int)JSVCall.Oper.GET_FIELD, slot, i, (field.IsStatic ? "true" : "false"), (field.IsStatic ? "" : ", this"))
                .Add("set: function (v) {{ return CS.Call({0}, {1}, {2}, {3}{4}, v); }}", (int)JSVCall.Oper.SET_FIELD, slot, i, (field.IsStatic ? "true" : "false"), (field.IsStatic ? "" : ", this"))
                .Out().Add("},");
            }
        }
        public static void BuildProperties(TextFile tfStatic, TextFile tfInst,
                                           Type type, List <MemberInfoEx> properties, int slot)
        {
            for (int i = 0; i < properties.Count; i++)
            {
                MemberInfoEx infoEx = properties[i];
                if (infoEx.Ignored)
                {
                    continue;
                }

                PropertyInfo property = infoEx.member as PropertyInfo;

                ParameterInfo[] ps            = property.GetIndexParameters();
                string          indexerParamA = string.Empty;
                string          indexerParamB = string.Empty;
                string          indexerParamC = string.Empty;
                for (int j = 0; j < ps.Length; j++)
                {
                    indexerParamA += "ind" + j.ToString();
                    indexerParamB += "ind" + j.ToString() + ", ";
                    if (j < ps.Length - 1)
                    {
                        indexerParamA += ", ";
                    }
                    indexerParamC += ", ind" + j.ToString();
                }

                MethodInfo[] accessors = property.GetAccessors();
                bool         isStatic  = accessors[0].IsStatic;

                // 特殊情况,当[]时,property.Name=Item
                string mName = Member_AddSuffix(property.Name, infoEx.GetOverloadIndex());

                TextFile tf = isStatic ? tfStatic : tfInst;
                tf.Add("get{0}: function ({1}) {{ return CS.Call({2}, {3}, {4}, {5}{6}{7}); }},",
                       mName, indexerParamA, (int)JSVCall.Oper.GET_PROPERTY, slot, i, (isStatic ? "true" : "false"), (isStatic ? "" : ", this"), indexerParamC);

                tf.Add("set{0}: function ({1}v) {{ return CS.Call({2}, {3}, {4}, {5}{6}{7}, v); }},",
                       mName, indexerParamB, (int)JSVCall.Oper.SET_PROPERTY, slot, i, (isStatic ? "true" : "false"), (isStatic ? "" : ", this"), indexerParamC);
            }
        }
Exemple #3
0
        static int PropertyInfoComparison(MemberInfoEx mi1, MemberInfoEx mi2)
        {
            PropertyInfo m1 = mi1.member as PropertyInfo;
            PropertyInfo m2 = mi2.member as PropertyInfo;

            // 实例函数在前
            if (!m1.GetAccessors()[0].IsStatic && m2.GetAccessors()[0].IsStatic)
            {
                return(-1);
            }
            if (m1.GetAccessors()[0].IsStatic && !m2.GetAccessors()[0].IsStatic)
            {
                return(1);
            }

            // 按名字字符串排序
            if (m1.Name != m2.Name)
            {
                return(string.Compare(m1.Name, m2.Name));
            }

            return(string.Compare(PropertyToString(m1), PropertyToString(m2)));
        }
Exemple #4
0
        static int MethodBaseComparison(MemberInfoEx mi1, MemberInfoEx mi2)
        {
            MethodBase m1 = mi1.member as MethodBase;
            MethodBase m2 = mi2.member as MethodBase;

            if (m1 == null && m2 != null)
            {
                return(-1);
            }
            if (m1 != null && m2 == null)
            {
                return(1);
            }
            if (m1 == null && m2 == null)
            {
                return(0);
            }

            // 实例函数在前
            if (!m1.IsStatic && m2.IsStatic)
            {
                return(-1);
            }
            if (m1.IsStatic && !m2.IsStatic)
            {
                return(1);
            }

            // 按名字字符串排序
            if (m1.Name != m2.Name)
            {
                return(string.Compare(m1.Name, m2.Name));
            }

            return(string.Compare(MethodToString(m1), MethodToString(m2)));
        }
Exemple #5
0
        public static ATypeInfo CreateTypeInfo(Type type)
        {
            ATypeInfo ti = new ATypeInfo();
            {
                var fields = type.GetFields(JSMgr.BindingFlagsField);
                for (int i = 0; i < fields.Length; i++)
                {
                    ti.Fields.Add(new MemberInfoEx(ti.Fields, fields[i], fields[i].IsStatic));
                }

                var pros = type.GetProperties(JSMgr.BindingFlagsProperty);
                for (int i = 0; i < pros.Length; i++)
                {
                    ti.Pros.Add(new MemberInfoEx(ti.Pros, pros[i], pros[i].GetAccessors()[0].IsStatic));
                }

                ti.Pros.Sort(PropertyInfoComparison);

                var methods = type.GetMethods(JSMgr.BindingFlagsMethod);
                for (int i = 0; i < methods.Length; i++)
                {
                    ti.Methods.Add(new MemberInfoEx(ti.Methods, methods[i], methods[i].IsStatic));
                }

                // 函数排序
                ti.Methods.Sort(MethodBaseComparison);

                var cons = type.GetConstructors();
                if (JSBindingSettings.NeedGenDefaultConstructor(type))
                {
                    // null 表示默认构造函数
                    var l = new List <ConstructorInfo>();
                    l.Add(null);
                    l.AddRange(cons);
                    cons = l.ToArray();
                }
                for (int i = 0; i < cons.Length; i++)
                {
                    ti.Cons.Add(new MemberInfoEx(ti.Cons, cons[i], false));
                }

                ti.Cons.Sort(MethodBaseComparison);
            }

            bool isStaticClass   = (type.IsClass && type.IsAbstract && type.IsSealed);
            bool isAbstractClass = (type.IsClass && type.IsAbstract);

            Dictionary <string, int> proAccessors = new Dictionary <string, int>();

            for (int i = 0; i < ti.Cons.Count; i++)
            {
                MemberInfoEx    infoEx = ti.Cons[i];
                ConstructorInfo con    = infoEx.member as ConstructorInfo;
                if (con == null)
                {
                    continue;
                }

                if (isAbstractClass ||
                    //type == typeof(UnityEngine.MonoBehaviour) ||
                    IsMemberObsolete(con) ||
                    JSBindingSettings.IsDiscard(type, con)
                    )
                {
                    infoEx.Ignored = true;
                    continue;
                }

                ParameterInfo[] ps = con.GetParameters();
                for (var k = 0; k < ps.Length; k++)
                {
                    Type pt = ps[k].ParameterType;
                    if (TypeIsPtr(pt))
                    {
                        infoEx.Ignored = true;
                        continue;
                    }
                }
            }

            for (int i = 0; i < ti.Fields.Count; i++)
            {
                MemberInfoEx infoEx = ti.Fields[i];
                FieldInfo    field  = infoEx.member as FieldInfo;

                if (typeof(System.Delegate).IsAssignableFrom(field.FieldType.BaseType))
                {
                    //Debug.Log("[field]" + type.ToString() + "." + ti.fields[i].Name + "is delegate!");
                }

                if (field.FieldType.ContainsGenericParameters ||
                    IsMemberObsolete(field) ||
                    JSBindingSettings.IsDiscard(type, field)
                    )
                {
                    infoEx.Ignored = true;
                }
            }

            for (int i = 0; i < ti.Pros.Count; i++)
            {
                MemberInfoEx infoEx = ti.Pros[i];
                PropertyInfo pro    = infoEx.member as PropertyInfo;

                if (typeof(System.Delegate).IsAssignableFrom(pro.PropertyType.BaseType))
                {
                    // Debug.Log("[property]" + type.ToString() + "." + pro.Name + "is delegate!");
                }

                MethodInfo[] accessors = pro.GetAccessors();
                foreach (var v in accessors)
                {
                    if (!proAccessors.ContainsKey(v.Name))
                    {
                        proAccessors.Add(v.Name, 0);
                    }
                }

                // Skip Obsolete
                if (IsMemberObsolete(pro) ||
                    TypeIsPtr(pro.PropertyType) ||
                    JSBindingSettings.IsDiscard(type, pro)
                    )
                {
                    infoEx.Ignored = true;
                }
            }

            for (int i = 0; i < ti.Methods.Count; i++)
            {
                MemberInfoEx infoEx = ti.Methods[i];
                MethodInfo   method = infoEx.member as MethodInfo;

                // skip non-static method in static class
                if ((isStaticClass && !method.IsStatic) ||
                    (method.IsSpecialName && proAccessors.ContainsKey(method.Name))
                    )
                {
                    infoEx.Ignored = true;
                    continue;
                }

                if (method.IsSpecialName)
                {
                    if (method.Name == "op_Addition" ||
                        method.Name == "op_Subtraction" ||
                        method.Name == "op_UnaryNegation" ||
                        method.Name == "op_Multiply" ||
                        method.Name == "op_Division" ||
                        method.Name == "op_Equality" ||
                        method.Name == "op_Inequality" ||

                        method.Name == "op_LessThan" ||
                        method.Name == "op_LessThanOrEqual" ||
                        method.Name == "op_GreaterThan" ||
                        method.Name == "op_GreaterThanOrEqual" ||

                        method.Name == "op_Implicit")
                    {
                        if (!method.IsStatic)
                        {
                            Debug.Log("忽略非静态特殊名字函数 " + type.Name + "." + method.Name);
                            infoEx.Ignored = true;
                            continue;
                        }
                    }
                    else
                    {
                        Debug.Log("忽略特殊名字函数 " + type.Name + "." + method.Name);
                        infoEx.Ignored = true;
                        continue;
                    }
                }

                // Skip Obsolete
                if (IsMemberObsolete(method))
                {
                    infoEx.Ignored = true;
                    continue;
                }

                ParameterInfo[] ps;
                bool            bDiscard = false;

                // 忽略掉类型带 T 的静态方法
                // 因为 SharpKit 调用时没有提供 T
                if (method.IsGenericMethodDefinition && /* || method.IsGenericMethod*/
                    method.IsStatic)
                {
                    ps = method.GetParameters();
                    for (int k = 0; k < ps.Length; k++)
                    {
                        if (ps[k].ParameterType.ContainsGenericParameters)
                        {
                            var Ts = JSDataExchangeMgr.RecursivelyGetGenericParameters(ps[k].ParameterType);
                            foreach (var t in Ts)
                            {
                                if (t.DeclaringMethod == null)
                                {
                                    bDiscard = true;
                                    break;
                                }
                            }
                            if (bDiscard)
                            {
                                break;
                            }
                        }
                    }
                    if (bDiscard)
                    {
                        Debug.LogWarning("忽略静态函数 " + type.Name + "." + method.Name);
                        infoEx.Ignored = true;
                        continue;
                    }
                }

                if (ShouldIgnoreTypeInM(type, method, method.ReturnType))
                {
                    Debug.Log(type.Name + "." + method.Name + " 忽略,因为返回值类型是逻辑类型");
                    infoEx.Ignored = true;
                    continue;
                }

                if (TypeIsPtr(method.ReturnType))
                {
                    Debug.Log(type.Name + "." + method.Name + " 忽略,因为返回值类型是 IntPtr");
                    infoEx.Ignored = true;
                    continue;
                }

                // 是否有 unsafe 的参数?
                bDiscard = false;
                ps       = method.GetParameters();
                for (var k = 0; k < ps.Length; k++)
                {
                    Type pt = ps[k].ParameterType;
                    if (TypeIsPtr(pt))
                    {
                        bDiscard = true;
                        break;
                    }
                }
                if (bDiscard)
                {
                    Debug.Log(type.Name + "." + method.Name + " 忽略,因为他有 IsPointer = true 的参数");
                    infoEx.Ignored = true;
                    continue;
                }

                bDiscard = false;
                for (var k = 0; k < ps.Length; k++)
                {
                    Type pt = ps[k].ParameterType;
                    if (ShouldIgnoreTypeInM(type, method, pt))
                    {
                        bDiscard = true;
                        break;
                    }
                }
                if (bDiscard)
                {
                    Debug.Log(type.Name + "." + method.Name + " 忽略,因为他的参数有逻辑类型");
                    infoEx.Ignored = true;
                    continue;
                }

                if (JSBindingSettings.IsDiscard(type, method))
                {
                    infoEx.Ignored = true;
                    continue;
                }
            }

            // 移除 Ignored 的项
            foreach (List <MemberInfoEx> lst in
                     new List <MemberInfoEx>[] { ti.Cons, ti.Fields, ti.Pros, ti.Methods })
            {
                for (int i = lst.Count - 1; i >= 0; i--)
                {
                    if (lst[i].Ignored)
                    {
                        lst.RemoveAt(i);
                    }
                }
            }
            return(ti);
        }
        static void GenInterfaceOrStructOrClass(Type type, TypeStatus ts,
                                                Func <Type, TypeStatus> getParent, Action <Type> onNewType)
        {
            TextFile tfFile = null;

            if (type.DeclaringType != null)
            {
                ts.IsInnerType = true;

                TypeStatus tsParent = getParent(type.DeclaringType);
                if (tsParent == null || tsParent.status == TypeStatus.Status.Wait)
                {
                    return;
                }

                if (tsParent.status == TypeStatus.Status.Ignored)
                {
                    ts.status = TypeStatus.Status.Ignored;
                    return;
                }

                tfFile = tsParent.tf.FindByTag("epos");
            }

            if (tfFile == null)
            {
                tfFile = new TextFile();
            }

            ts.tf     = tfFile;
            ts.status = TypeStatus.Status.Exported;

            GeneratorHelp.ATypeInfo ti = GeneratorHelp.CreateTypeInfo(type);

            StringBuilder sb   = new StringBuilder();
            TextFile      tfNs = tfFile;

            //string dir = Dir;
            if (type.DeclaringType == null &&
                !string.IsNullOrEmpty(type.Namespace))
            {
                tfNs = tfFile.Add("namespace {0}", type.Namespace).BraceIn();
                tfNs.BraceOut();
            }

            tfNs.Add("[Bridge.FileName(\"csw\")]");

            TextFile tfClass = null;

            sb.Remove(0, sb.Length);
            {
                if (type.IsPublic || type.IsNestedPublic)
                {
                    sb.Append("public ");
                }

                if (type.IsClass)
                {
                    if (type.IsAbstract && type.IsSealed)
                    {
                        sb.Append("static ");
                    }
                    //else if (type.IsAbstract)
                    //    sb.Append("abstract ");
                    //else if (type.IsSealed)
                    //    sb.Append("sealed ");

                    //if (type.is)
                }

                if (type.IsInterface)
                {
                    sb.Append("interface ");
                }
                else if (type.IsValueType)
                {
                    sb.Append("struct ");
                }
                else
                {
                    sb.Append("class ");
                }

                string className = type.CsFullName(CsNameOption.CompilableWithT);
                int    dot       = className.LastIndexOf(".");
                if (dot >= 0)
                {
                    className = className.Substring(dot + 1);
                }
                sb.Append(className);

                Type   vBaseType  = type.ValidBaseType();
                Type[] interfaces = type.GetDeclaringInterfaces();
                if (vBaseType != null || interfaces.Length > 0)
                {
                    sb.Append(" : ");

                    args a = new args();
                    if (vBaseType != null)
                    {
                        a.Add(typefn(vBaseType, type.Namespace));
                        onNewType(vBaseType);
                    }
                    foreach (var i in interfaces)
                    {
                        a.Add(typefn(i, type.Namespace));
                        onNewType(i);
                    }

                    sb.Append(a.ToString());
                }

                tfClass = tfNs.Add(sb.ToString()).BraceIn();
                tfClass.BraceOut();
            }

            tfClass.AddTag("epos");

            for (int i = 0; i < ti.Fields.Count; i++)
            {
                MemberInfoEx infoEx = ti.Fields[i];
                FieldInfo    field  = infoEx.member as FieldInfo;
                tfClass.Add("public {0}{1} {2};", (field.IsStatic ? "static " : ""), typefn(field.FieldType, type.Namespace), field.Name);

                onNewType(field.FieldType);
            }
            if (ti.Fields.Count > 0)
            {
                tfClass.AddLine();
            }

            for (int i = 0; i < ti.Cons.Count; i++)
            {
                MemberInfoEx    infoEx = ti.Cons[i];
                ConstructorInfo con    = infoEx.member as ConstructorInfo;

                if (type.IsValueType)
                {
                    // 结构体不需要无参数构造函数
                    if (con == null || con.GetParameters().Length == 0)
                    {
                        continue;
                    }
                }

                string ctorName = type.Name;
                if (type.IsGenericTypeDefinition)
                {
                    int flag = ctorName.LastIndexOf('`');
                    if (flag >= 0)
                    {
                        ctorName = ctorName.Substring(0, flag);
                    }
                }
                tfClass.Add("public extern {0}({1});", ctorName, con == null ? "" : Ps2String(type, con.GetParameters()));

                if (con != null)
                {
                    foreach (var p in con.GetParameters())
                    {
                        onNewType(p.ParameterType);
                    }
                }
            }
            if (ti.Cons.Count > 0)
            {
                tfClass.AddLine();
            }

            handlePros(tfClass, type, ti, onNewType);

            if (ti.Pros.Count > 0)
            {
                tfClass.AddLine();
            }

            handleMethods(tfClass, type, ti, onNewType);
            if (!type.IsInterface)
            {
                handleInterfaceProblems(tfClass, type, onNewType);
            }
        }
        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; }");
                }
            }
        }
        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);
                }
            }
        }
        // can handle all methods
        public static void BuildMethods(TextFile tfStatic, TextFile tfInst,
                                        Type type, List <MemberInfoEx> methods, int slot)
        {
            for (int i = 0; i < methods.Count; i++)
            {
                MemberInfoEx infoEx = methods[i];
                if (infoEx.Ignored)
                {
                    continue;
                }

                MethodInfo method = infoEx.member as MethodInfo;

                StringBuilder   sbFormalParam = new StringBuilder();
                StringBuilder   sbActualParam = new StringBuilder();
                ParameterInfo[] paramS        = method.GetParameters();
                TextFile        tfInitT       = new TextFile();
                int             TCount        = 0;

                // add T to formal param
                if (method.IsGenericMethodDefinition)
                {
                    Type[] GAs = method.GetGenericArguments();
                    for (int j = 0; j < GAs.Length; j++)
                    {
                        sbFormalParam.AppendFormat("{0}", GAs[j].Name);
                        if (j < GAs.Length - 1 || paramS.Length > 0)
                        {
                            sbFormalParam.Append(", ");
                        }

                        tfInitT.Add("var ${0} = Bridge.Reflection.getTypeFullName({0});", GAs[j].Name);
                        sbActualParam.AppendFormat(", ${0}", GAs[j].Name);
                    }
                }

                int L = paramS.Length;
                for (int j = 0; j < L; j++)
                {
                    sbFormalParam.AppendFormat("a{0}/* {1} */{2}", j, paramS[j].ParameterType.Name, (j == L - 1 ? "" : ", "));

                    // 特殊处理
                    // 配合 UnityEngineManual.GameObject_AddComponent__Type
                    if (j == 0 &&
                        type == typeof(GameObject) && method.Name == "AddComponent" &&
                        paramS.Length == 1 && paramS[j].ParameterType == typeof(Type))
                    {
                        sbActualParam.AppendFormat(", Bridge.Reflection.getTypeFullName(a{0})", j);
                    }
                    else
                    {
                        sbActualParam.AppendFormat(", a{0}", j);
                    }
                }

                //int TCount = method.GetGenericArguments().Length;

                string methodName = method.Name;

                // if (methodName == "ToString") { methodName = "toString"; }

                string mName = Member_AddSuffix(methodName, infoEx.GetOverloadIndex(), TCount);

                TextFile tf = method.IsStatic ? tfStatic : tfInst;

                string strReturn = string.Format("return CS.Call({0}, {1}, {2}, {3}{4});", (int)JSVCall.Oper.METHOD, slot, i, (method.IsStatic ? "true" : "false"), (method.IsStatic ? "" : ", this") + sbActualParam.ToString());
                if (tfInitT.Ch.Count > 0)
                {
                    tf.Add("{0}: function ({1}) {{", mName, sbFormalParam.ToString())
                    .In()
                    .Add(tfInitT.Ch)
                    .Add(strReturn)
                    .Out()
                    .Add("},");
                }
                else
                {
                    tf.Add("{0}: function ({1}) {{ {2} }},", mName, sbFormalParam.ToString(), strReturn);
                }
            }
        }
        public static void BuildConstructors(TextFile tfInst, Type type, List <MemberInfoEx> constructors, int slot)
        {
            var argActual = new args();
            var argFormal = new args();

            for (int i = 0; i < constructors.Count; i++)
            {
                MemberInfoEx infoEx = constructors[i];
                if (infoEx.Ignored)
                {
                    continue;
                }
                ConstructorInfo con = infoEx.member as ConstructorInfo;

                TextFile        tf = new TextFile();
                ParameterInfo[] ps = con == null ? new ParameterInfo[0] : con.GetParameters();

                argActual.Clear().Add(
                    (int)JSVCall.Oper.CONSTRUCTOR, // OP
                    slot,
                    i,                             // NOTICE
                    "true",                        // IsStatics
                    "this"
                    );

                argFormal.Clear();

                // add T to formal param
                Type[] GAs = null;
                if (type.IsGenericTypeDefinition)
                {
                    GAs = type.GetGenericArguments();
                    for (int j = 0; j < GAs.Length; j++)
                    {
                        //argFormal.Add("t" + j + "");
                        argActual.AddFormat("${0}", GAs[j].Name);
                    }
                }

                //StringBuilder sbFormalParam = new StringBuilder();
                //StringBuilder sbActualParam = new StringBuilder();
                for (int j = 0; j < ps.Length; j++)
                {
                    argFormal.Add("a" + j.ToString());
                    argActual.Add("a" + j.ToString());
                }

                string mName = Ctor_Name(infoEx.GetOverloadIndex());

                // 特殊处理 - MonoBehaviour 不需要构造函数内容
                if (type == typeof(MonoBehaviour))
                {
                    tf.Add("{0}: function ({1}) {{}},", mName, argFormal);
                }
                // 再次特殊处理
                else if (type == typeof(WaitForSeconds))
                {
                    tf.Add("{0}: function ({1}) {{", mName, argFormal)
                    .In()
                    .Add("this.$totalTime = a0;")
                    .Add("this.$elapsedTime = 0;")
                    .Add("this.$finished = false;")
                    .Out().Add("},");
                }
                else
                {
                    TextFile tfFun = tf.Add("{0}: function ({1}) {{", mName, argFormal)
                                     .In();

                    if (type.IsGenericTypeDefinition)
                    {
                        tfFun.Add("var $GAs = Bridge.Reflection.getGenericArguments(Bridge.getType(this));");
                        for (int j = 0; j < GAs.Length; j++)
                        {
                            tfFun.Add("var ${0} = Bridge.Reflection.getTypeFullName($GAs[{1}]);",
                                      GAs[j].Name, j);
                        }
                    }

                    tfFun.Add("CS.Call({0});", argActual)
                    .Out().Add("},");
                }
                tfInst.Add(tf.Ch);
            }
        }
        public static void BuildProperties(TextFile tfStatic, TextFile tfInst,
                                           TextFile tfAlias, Type[] declInterfs,
                                           Type type, List <MemberInfoEx> properties, int slot)
        {
            for (int i = 0; i < properties.Count; i++)
            {
                MemberInfoEx infoEx = properties[i];
                if (infoEx.Ignored)
                {
                    continue;
                }

                PropertyInfo property = infoEx.member as PropertyInfo;

                ParameterInfo[] ps            = property.GetIndexParameters();
                string          indexerParamA = string.Empty;
                string          indexerParamB = string.Empty;
                string          indexerParamC = string.Empty;
                for (int j = 0; j < ps.Length; j++)
                {
                    indexerParamA += "ind" + j.ToString();
                    indexerParamB += "ind" + j.ToString() + ", ";
                    if (j < ps.Length - 1)
                    {
                        indexerParamA += ", ";
                    }
                    indexerParamC += ", ind" + j.ToString();
                }

                MethodInfo[] accessors = property.GetAccessors();
                bool         isStatic  = accessors[0].IsStatic;

                // 特殊情况,当[]时,property.Name=Item
                string mName = Pro_AddSuffix(property.Name, infoEx.GetOverloadIndex());


                if (tfAlias != null)
                {
                    Type iType;
                    if (property.CanRead && shouldAddAlias(type, accessors[0], declInterfs, out iType))
                    {
                        tfAlias.Add("\"get{0}\", \"{1}\",", mName, getAliasName(iType, "get" + mName));
                    }
                    if (property.CanWrite && accessors.Length > 1 && shouldAddAlias(type, accessors[1], declInterfs, out iType))
                    {
                        tfAlias.Add("\"set{0}\", \"{1}\",", mName, getAliasName(iType, "set" + mName));
                    }
                }

                TextFile tf = isStatic ? tfStatic : tfInst;
                if (property.CanRead)
                {
                    tf.Add("get{0}: function ({1}) {{ return CS.Call({2}, {3}, {4}, {5}{6}{7}); }},",
                           mName, indexerParamA, (int)JSVCall.Oper.GET_PROPERTY, slot, i, (isStatic ? "true" : "false"), (isStatic ? "" : ", this"), indexerParamC);
                }
                if (property.CanWrite)
                {
                    tf.Add("set{0}: function ({1}v) {{ return CS.Call({2}, {3}, {4}, {5}{6}{7}, v); }},",
                           mName, indexerParamB, (int)JSVCall.Oper.SET_PROPERTY, slot, i, (isStatic ? "true" : "false"), (isStatic ? "" : ", this"), indexerParamC);
                }
            }
        }