Exemplo n.º 1
0
        public static TextFile Build_GetDelegate(string getDelegateFunctionName, Type delType)
        {
            TextFile tf    = new TextFile();
            TextFile tfFun = tf.Add("JSDataExchangeMgr.GetJSArg<{0}>(() => ", JSNameMgr.CsFullName(delType)).BraceIn();

            {
                TextFile tfIf = tfFun.Add("if (JSApi.isFunctionS((int)JSApi.GetType.Arg))").BraceIn();
                {
                    tfIf.Add("return {0}(JSApi.getFunctionS((int)JSApi.GetType.Arg));", getDelegateFunctionName);

                    tfIf.BraceOut();
                }

                TextFile tfElse = tfFun.Add("else").BraceIn();
                {
                    tfElse.Add("return ({0})JSMgr.datax.getObject((int)JSApi.GetType.Arg);", JSNameMgr.CsFullName(delType));

                    tfElse.BraceOut();
                }

                tfFun.BraceOut().Add(");");
            }

            return(tf);
        }
Exemplo n.º 2
0
        public static string GetMethodArg_DelegateFuncionName(Type classType, string methodName, int methodTag, int argIndex)
        {
            // append Method Index if still conflicts
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("{0}_{1}_GetDelegate_member{2}_arg{3}", classType.Name, methodName, methodTag, argIndex);
            return(JSNameMgr.HandleFunctionName(sb.ToString()));
        }
Exemplo n.º 3
0
        static TextFile GenEnum()
        {
            TextFile tf = new TextFile();

            string typeName = type.ToString();
            // tf.AddLine().Add("// {0}", typeName);

            // remove name space
            int lastDot = typeName.LastIndexOf('.');

            if (lastDot >= 0)
            {
                typeName = typeName.Substring(lastDot + 1);
            }

            if (typeName.IndexOf('+') >= 0)
            {
                return(null);
            }

            TextFile tfDef = tf.Add("Bridge.define(\"{0}\", {{", JSNameMgr.JsFullName(type)).In();

            tfDef.Add("$kind: \"enum\",");
            TextFile tfSta = tfDef.Add("statics: {").In();

            Type uType = Enum.GetUnderlyingType(type);

            FieldInfo[] fields = type.GetFields(BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static);
            for (int i = 0; i < fields.Length; i++)
            {
                string v = "";
                if (uType == typeof(ulong))
                {
                    v = System.Convert.ToUInt64(fields[i].GetValue(null)).ToString();
                }
                else
                {
                    v = System.Convert.ToInt64(fields[i].GetValue(null)).ToString();
                }

                tfSta.Add("{0}: {1}{2}", fields[i].Name, v, i == fields.Length - 1 ? "" : ",");
            }
            tfSta.BraceOut();
            //tfDef.BraceOutSC();
            tfDef.Out().Add("});");

            return(tf);
        }
        static string typefn(Type tType, string eraseNs, CsNameOption opt = CsNameOption.Compilable)
        {
            string fn = JSNameMgr.CsFullName(tType, opt);

            if (eraseNs == "no-namespace")
            {
                int dot = fn.LastIndexOf('.');
                if (dot >= 0)
                {
                    fn = fn.Substring(dot + 1);
                }
            }
            else if (!string.IsNullOrEmpty(eraseNs) &&
                     fn.StartsWith(eraseNs + "."))
            {
                fn = fn.Substring(eraseNs.Length + 1);
            }
            return(fn);
        }
Exemplo n.º 5
0
        public TextFile Get_GetParam(Type t)
        {
            elementType = t.GetElementType();
            if (elementType.IsArray)
            {
                //...error
            }
            bool   needCast;
            string getVal = JSDataExchangeMgr.GetMetatypeKeyword(elementType, out needCast);

            var arrayFullName   = string.Empty;
            var elementFullName = string.Empty;

            if (elementType.IsGenericParameter)
            {
                arrayFullName   = "object[]";
                elementFullName = "object";
            }
            else
            {
                arrayFullName   = JSNameMgr.CsFullName(t);
                elementFullName = JSNameMgr.CsFullName(elementType);
            }

            TextFile tf = new TextFile();

            tf.AddMultiline(@"JSDataExchangeMgr.GetJSArg<{0}>(() => 
{{
    int jsObjID = JSApi.getObject((int)JSApi.GetType.Arg);
    int length = jsObjID == 0 ? 0 : JSApi.getArrayLength(jsObjID);
    var ret = new {1}[length];
    for (var i = 0; i < length; i++)
    {{
        JSApi.getElement(jsObjID, i);
        ret[i] = ({1}){2}((int)JSApi.GetType.SaveAndRemove);
    }}
    return ret;
}})",
                            arrayFullName, elementFullName, getVal);

            return(tf);
        }
Exemplo n.º 6
0
        public string Get_Return(string expVar)
        {
            if (elementType == null)
            {
                Debug.LogError("JSDataExchange_Arr elementType == null !!");
                return("");
            }

            StringBuilder sb = new StringBuilder();
            bool          needCast;
            string        getValMethod = JSDataExchangeMgr.GetMetatypeKeyword(elementType, out needCast).Replace("get", "set");

            // 2015.Sep.2
            // +判断arrRet为null的情况
            if (elementType.ContainsGenericParameters)
            {
                sb.AppendFormat("    var arrRet = (Array){0};\n", expVar)
                .AppendFormat("    for (int i = 0; arrRet != null && i < arrRet.Length; i++)\n")
                .Append("    [[\n")
                .AppendFormat("        {0}((int)JSApi.SetType.SaveAndTempTrace, arrRet.GetValue(i));\n", getValMethod)
                .AppendFormat("        JSApi.moveSaveID2Arr(i);\n")
                .AppendFormat("    ]]\n")
                .AppendFormat("    JSApi.setArrayS((int)JSApi.SetType.Rval, (arrRet != null ? arrRet.Length : 0), true);");
            }
            else
            {
                sb.AppendFormat("    var arrRet = ({0}[]){1};\n", JSNameMgr.CsFullName(elementType), expVar)
                .AppendFormat("    for (int i = 0; arrRet != null && i < arrRet.Length; i++)\n")
                .Append("    [[\n")
                .AppendFormat("        {0}((int)JSApi.SetType.SaveAndTempTrace, {1}arrRet[i]);\n", getValMethod, elementType.IsEnum ? "(int)" : "")
                .AppendFormat("        JSApi.moveSaveID2Arr(i);\n")
                .AppendFormat("    ]]\n")
                .AppendFormat("    JSApi.setArrayS((int)JSApi.SetType.Rval, (arrRet != null ? arrRet.Length : 0), true);");
            }

            sb.Replace("[[", "{");
            sb.Replace("]]", "}");

            return(sb.ToString());
        }
Exemplo n.º 7
0
        public static bool CheckClasses(out Type[] arrEnums, out Type[] arrClasses,
                                        out HashSet <string> bridgeTypes)
        {
            arrEnums   = null;
            arrClasses = null;

            var  sb = new StringBuilder();
            bool ok = true;

            bridgeTypes = LoadBridgeDefinedTypes();

            foreach (var e in enums)
            {
                if (bridgeTypes.Contains(e.FullName))
                {
                    sb.AppendFormat("Bridge已包含\"{0}\",无需导出", e.FullName);
                    ok = false;

                    continue;
                }
            }
            if (ok)
            {
                arrEnums = enums;
            }

            HashSet <Type> wanted = new HashSet <Type>();

            foreach (var type in classes)
            {
                if (typeof(System.Delegate).IsAssignableFrom(type))
                {
                    sb.AppendFormat("Delegate \"{0}\" 不能导出\n",
                                    JSNameMgr.CsFullName(type));
                    ok = false;

                    continue;
                }

                if (type.IsGenericType && !type.IsGenericTypeDefinition)
                {
                    sb.AppendFormat("\"{0}\" 不能导出,换成 \"{1}\"\n",
                                    JSNameMgr.CsFullName(type), JSNameMgr.CsFullName(type.GetGenericTypeDefinition()));
                    ok = false;

                    continue;
                }

                if (type.IsInterface)
                {
                    sb.AppendFormat("接口 \"{0}\" 不需要配置。如果有配置继承这个接口的类,则这个接口会自动添加\n",
                                    JSNameMgr.CsFullName(type));
                    ok = false;

                    continue;
                }

                if (wanted.Contains(type))
                {
                    sb.AppendFormat("\"{0}\" 配了多个.\n",
                                    JSNameMgr.CsFullName(type));
                    ok = false;

                    continue;
                }

                if (bridgeTypes.Contains(type.FullName))
                {
                    sb.AppendFormat("Bridge已包含\"{0}\",无需导出", type.FullName);
                    ok = false;

                    continue;
                }

                wanted.Add(type);
            }

            // 自动添加基类
            foreach (var typeb in wanted.ToArray())
            {
                Type type      = typeb;
                Type vBaseType = type.ValidBaseType();
                while (vBaseType != null)
                {
                    if (!bridgeTypes.Contains(vBaseType.FullName) &&
                        !wanted.Contains(vBaseType) &&
                        !(vBaseType.IsGenericType && !vBaseType.IsGenericTypeDefinition)
                        //&&
                        //!IsDiscardType(baseType)
                        )
                    {
                        wanted.Add(vBaseType);
                    }
                    vBaseType = vBaseType.ValidBaseType();
                }
            }

            // 自动添加接口
            foreach (var typeb in wanted.ToArray())
            {
                Type   type       = typeb;
                Type[] interfaces = type.GetInterfaces();
                for (int i = 0; i < interfaces.Length; i++)
                {
                    Type   ti         = interfaces[i];
                    string tiFullName = JSNameMgr.CsFullName(ti);
                    if (tiFullName.Contains("<") || tiFullName.Contains(">"))
                    {
                        continue;
                    }

                    if (!bridgeTypes.Contains(interfaces[i].FullName) &&
                        !wanted.Contains(ti)
                        //&&
                        //!IsDiscardType(ti)
                        )
                    {
                        wanted.Add(ti);
                    }
                }
            }

            if (!ok)
            {
                Debug.LogError(sb);
                return(false);
            }

            List <Type> lst = wanted.ToList();

            // 对 lst 进行排序
            // Bridge.js 假设基类在前(接口也算)
            // var baseType = extend[j],
            //   baseI = (baseType.$interfaces || []).concat(baseType.$baseInterfaces || []);
            {
                Dictionary <Type, int> dict = new Dictionary <Type, int>();
                foreach (var type in wanted)
                {
                    dict.Add(type, 0);
                }

                while (true)
                {
                    bool bC = false;
                    foreach (Type type in dict.Keys.ToArray())
                    {
                        int v = dict[type];
                        if (v != 0)
                        {
                            continue;
                        }

                        bool   allParentResolved = true;
                        int    maxParentValue    = 0;
                        Type[] interfaces        = type.GetInterfaces();
                        foreach (var interf in interfaces)
                        {
                            if (dict.ContainsKey(interf))
                            {
                                if (dict[interf] == 0)
                                {
                                    allParentResolved = false;
                                    break;
                                }
                                else
                                {
                                    maxParentValue = Math.Max(maxParentValue, dict[interf]);
                                }
                            }
                        }

                        Type baseType = type.ValidBaseType();
                        if (allParentResolved)
                        {
                            if (baseType != null &&
                                dict.ContainsKey(baseType))
                            {
                                if (dict[baseType] == 0)
                                {
                                    allParentResolved = false;
                                }
                                else
                                {
                                    maxParentValue = Math.Max(maxParentValue, dict[baseType]);
                                }
                            }
                        }

                        if (allParentResolved)
                        {
                            dict[type] = maxParentValue + 1;
                        }
                        else
                        {
                            bC = true;
                        }
                    }

                    if (!bC)
                    {
                        break;
                    }
                }

                lst.Sort((t1, t2) => (dict[t1] < dict[t2] ? -1 : (dict[t1] > dict[t2] ? 1 : 0)));
            }

            // 打印最终要导出的类型
            sb.Remove(0, sb.Length);
            sb.AppendLine("最终要导出的类型:");
            foreach (var t in lst)
            {
                sb.AppendLine(JSNameMgr.CsFullName(t));
            }
            Debug.Log(sb.ToString());

            arrClasses = lst.ToArray();
            return(true);
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
 public static string SharpKitClassName(Type type)
 {
     return(JSNameMgr.JsFullName(type));
 }
Exemplo n.º 10
0
        //
        // arg: a,b,c
        //
        public static TextFile BuildCallString(Type classType, MemberInfo memberInfo, string argList, MemberFeature features, object newValue = null /* string 或 TextFile */)
        {
            bool   bGenericT    = classType.IsGenericTypeDefinition;
            string memberName   = memberInfo.Name;
            bool   bIndexer     = ((features & MemberFeature.Indexer) > 0);
            bool   bStatic      = ((features & MemberFeature.Static) > 0);
            bool   bStruct      = classType.IsValueType;
            string typeFullName = JSNameMgr.CsFullName(classType);
            bool   bField       = (memberInfo is FieldInfo);
            bool   bProperty    = (memberInfo is PropertyInfo);
            bool   bGet         = ((features & MemberFeature.Get) > 0);
            bool   bSet         = ((features & MemberFeature.Set) > 0);

            if ((bGet && bSet) || (!bGet && !bSet))
            {
                return(null);
            }

            TextFile tf = new TextFile();

            if (bField || bProperty)
            {
                if (!bGenericT)
                {
                    var strThis = typeFullName;
                    if (!bStatic)
                    {
                        strThis = "_this";
                        tf.Add("{0} _this = ({0})vc.csObj;", typeFullName);
                    }

                    string access = bIndexer
                         ? string.Format("{0}[{1}]", strThis, argList)
                         : string.Format("{0}.{1}", strThis, memberName);

                    if (bGet)
                    {
                        tf.Add("var result = {0};", access);
                    }
                    else
                    {
                        if (newValue is string)
                        {
                            tf.Add("{0} = {1};", access, newValue);
                        }
                        else
                        {
                            tf.Add("{0} = ", access).In().Add((newValue as TextFile).Ch).Out().Add(";");
                        }

                        if (!bStatic && bStruct)
                        {
                            tf.Add("JSMgr.changeJSObj(vc.jsObjID, _this);");
                        }
                    }
                }
                else
                {
                    // convention: name 'member'
                    if (bIndexer || !bIndexer) // both indexer and not indexer enters
                    {
                        string objs = (bStatic ? "null" : "vc.csObj");
                        if (bProperty)
                        {
                            if (bGet)
                            {
                                tf.Add("var result = member.GetValue({0}, new object[]{{{1}}});",
                                       objs,
                                       argList);
                            }
                            else
                            {
                                if (newValue is string)
                                {
                                    tf.Add("member.SetValue({0}, {1}, new object[]{{{2}}});",
                                           objs,
                                           newValue,
                                           argList);
                                }
                                else
                                {
                                    tf.Add("member.SetValue({0}, ", objs)
                                    .In()
                                    .Add((newValue as TextFile).Ch)
                                    .Out()
                                    .Add(", new object[]{{{0}}});", argList);
                                }
                            }


                            //tf.Add("{4}member.{0}({1}, {2}new object[]{{{3}}});",
                            //    bGet ? "GetValue" : "SetValue",
                            //    bStatic ? "null" : "vc.csObj",
                            //    bSet ? newValue + ", " : "",
                            //    argList,
                            //    bGet ? "var result = " : "");
                        }
                        else
                        {
                            if (bGet)
                            {
                                tf.Add("var result = member.GetValue({0});", objs);
                            }
                            else
                            {
                                if (newValue is string)
                                {
                                    tf.Add("member.SetValue({0}, {1});", objs, newValue);
                                }
                                else
                                {
                                    tf.Add("member.SetValue({0}, ", objs).In().Add((newValue as TextFile).Ch).Out().Add(");");
                                }
                            }

                            //tf.Add("{3}member.{0}({1}{2});",
                            //    bGet ? "GetValue" : "SetValue",
                            //    bStatic ? "null" : "vc.csObj",
                            //    bSet ? ", " + newValue : "",
                            //    bGet ? "var result = " : "");
                        }
                    }
                }
            }
            return(tf);
        }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
0
        public static string Get_Return(Type type, string expVar)
        {
            if (type == typeof(void))
            {
                return(expVar + ";");
            }

            if (type.IsArray)
            {
                arrayExchange.elementType = type.GetElementType();
                if (arrayExchange.elementType.IsArray)
                {
                    Debug.LogError("Return [][] not supported");
                    return(string.Empty);
                }
                //            else if (arrayExchange.elementType.ContainsGenericParameters)
                //            {
                //                Debug.LogError(" Return T[] not supported");
                //                return "/* Return T[] is not supported */";
                //            }

                return(arrayExchange.Get_Return(expVar));
            }
            else
            {
                var  sb = new StringBuilder();
                bool needCast;
                var  keyword = GetMetatypeKeyword(type, out needCast).Replace("get", "set");
                if (type.IsPrimitive)
                {
                    sb.AppendFormat("{0}((int)JSApi.SetType.Rval, ({1})({2}));", keyword, JSNameMgr.CsFullName(type), expVar);
                }
                else if (type.IsEnum)
                {
                    sb.AppendFormat("{0}((int)JSApi.SetType.Rval, (int){1});", keyword, expVar);
                }
                else
                {
                    sb.AppendFormat("{0}((int)JSApi.SetType.Rval, {1});", keyword, expVar);
                }

                return(sb.ToString());
            }
        }
Exemplo n.º 13
0
        // Editor only
        public static ParamHandler Get_ParamHandler(Type type, int paramIndex, bool isRef, bool isOut)
        {
            ParamHandler ph = new ParamHandler();

            ph.argName = "arg" + paramIndex.ToString();

            if (IsDelegateDerived(type))
            {
                Debug.LogError("Delegate derived class should not get here");
                return(ph);
            }

            bool bTOrContainsT = (type.IsGenericParameter || type.ContainsGenericParameters);

            string typeFullName;

            if (bTOrContainsT)
            {
                typeFullName = "object";
            }
            else
            {
                typeFullName = JSNameMgr.CsFullName(type);
            }

            if (isRef || isOut)
            {
                type = type.GetElementType();
            }
            if (type.IsArray)
            {
                ph.getter = new TextFile()
                            .Add("{0} {1} = ", typeFullName, ph.argName)
                            .In()
                            .Add(arrayExchange.Get_GetParam(type).Ch)
                            .Out()
                            .Add(";");
            }
            else
            {
                bool   needCast;
                string keyword = GetMetatypeKeyword(type, out needCast);
                if (keyword == string.Empty)
                {
                    Debug.LogError("keyword is empty: " + type.Name);
                    return(ph);
                }

                if (isOut)
                {
                    ph.getter = new TextFile()
                                .Add("int r_arg{0} = JSApi.incArgIndex();", paramIndex)
                                .Add("{0} {1}{2};", typeFullName, ph.argName, bTOrContainsT ? " = null" : "");
                }
                else if (isRef)
                {
                    ph.getter = new TextFile()
                                .Add("int r_arg{0} = JSApi.getArgIndex();", paramIndex)
                                .Add("{0} {1} = ({0}){2}((int)JSApi.GetType.ArgRef);", typeFullName, ph.argName, keyword);
                }
                else
                {
                    if (needCast)
                    {
                        ph.getter = new TextFile()
                                    .Add("{0} {1} = ({0}){2}((int)JSApi.GetType.Arg);", typeFullName, ph.argName, keyword);
                    }
                    else
                    {
                        ph.getter = new TextFile()
                                    .Add("{0} {1} = {2}((int)JSApi.GetType.Arg);", typeFullName, ph.argName, keyword);
                    }
                }

                if (isOut || isRef)
                {
                    TextFile tf = new TextFile();
                    if (bTOrContainsT)
                    {
                        // TODO
                        // sorry, 'arr_t' is written in CSGenerator2.cs
                        tf.Add("{0} = arr_t[{1}];", ph.argName, paramIndex);
                    }

                    tf.Add("JSApi.setArgIndex(r_arg{0});", paramIndex)
                    .Add("{0}((int)JSApi.SetType.ArgRef, {1});", keyword.Replace("get", "set"), ph.argName);

                    ph.updater = tf;
                }
            }
            return(ph);
        }