Esempio n. 1
0
        // 写入绑定代码
        protected void WriteCSMethodBinding(MethodBaseBindingInfo <T> bindingInfo, T method, string argc, bool isVararg)
        {
            // 是否接管 cs 绑定代码生成
            var transform = cg.bindingManager.GetTypeTransform(method.DeclaringType);

            if (transform != null && transform.OnBinding(BindingPoints.METHOD_BINDING_FULL, method, cg))
            {
                return;
            }

            var isExtension = BindingManager.IsExtensionMethod(method);
            // var isRaw = method.IsDefined(typeof(JSCFunctionAttribute));
            var parameters = method.GetParameters();
            var in_params  = new List <ParameterInfo>();
            var out_params = new List <ParameterInfo>();

            SplitParamters(parameters, isExtension ? 1 : 0, in_params, out_params);
            var caller     = this.cg.AppendGetThisCS(method);
            var returnType = GetReturnType(method);

            // if (isRaw)
            // {
            //     do
            //     {
            //         if (!isExtension)
            //         {
            //             if (returnType == typeof(int) && in_params.Count == 1)
            //             {
            //                 var p = in_params[0];
            //                 if (p.ParameterType == typeof(IntPtr) && !p.IsOut)
            //                 {
            //                     cg.cs.AppendLine($"return {caller}.{method.Name}(ctx);");
            //                     return;
            //                 }
            //             }
            //             cg.bindingManager.Error($"invalid JSCFunction definition: {method}");
            //             break;
            //         }
            //         cg.bindingManager.Error($"Extension as JSCFunction is not supported: {method}");
            //     } while (false);
            // }

            if (returnType == null || returnType == typeof(void))
            {
                // 方法本身没有返回值
                this.BeginInvokeBinding();
                cg.cs.AppendLine($"{this.GetInvokeBinding(caller, method, isVararg, isExtension, argc, parameters)};");
                this.EndInvokeBinding();
                var backVars = out_params.Count > 0 ? _WriteBackParametersByRef(isExtension, out_params, null) : null;

                if (!method.IsStatic && method.DeclaringType.IsValueType) // struct 非静态方法 检查 Mutable 属性
                {
                    if (!string.IsNullOrEmpty(caller))
                    {
                        cg.cs.AppendLine($"js_rebind_this(ctx, this_obj, {caller});");
                    }
                }

                if (string.IsNullOrEmpty(backVars))
                {
                    this.InvokeVoidReturn();
                }
                else
                {
                    cg.cs.AppendLine("return {0};", backVars);
                }
            }
            else
            {
                var retVar   = "ret"; // cs return value var name
                var retJsVar = "ret_js";
                this.BeginInvokeBinding();
                cg.cs.AppendLine($"var {retVar} = {this.GetInvokeBinding(caller, method, isVararg, isExtension, argc, parameters)};");
                this.EndInvokeBinding();

                var retPusher = cg.AppendMethodReturnValuePusher(method, returnType, retVar);
                cg.cs.AppendLine("var {0} = {1};", retJsVar, retPusher);
                cg.cs.AppendLine("if (JSApi.JS_IsException({0}))", retJsVar);
                using (cg.cs.Block())
                {
                    cg.cs.AppendLine("return {0};", retJsVar);
                }
                var backVars = out_params.Count > 0 ? _WriteBackParametersByRef(isExtension, out_params, retJsVar) : retJsVar;
                cg.cs.AppendLine("return {0};", backVars);
            }
        }
Esempio n. 2
0
        protected List <ParameterInfo> WriteTSDeclaration(T method, MethodBaseBindingInfo <T> bindingInfo)
        {
            var    isExtension   = BindingManager.IsExtensionMethod(method);
            var    refParameters = new List <ParameterInfo>();
            string tsMethodDeclaration;

            this.cg.AppendJSDoc(method);
            if (this.cg.bindingManager.GetTSMethodDeclaration(method, out tsMethodDeclaration))
            {
                this.cg.tsDeclare.AppendLine(tsMethodDeclaration);
                return(refParameters);
            }
            var isRaw = method.IsDefined(typeof(JSCFunctionAttribute));
            //TODO: 需要处理参数类型归并问题, 因为如果类型没有导入 ts 中, 可能会在声明中出现相同参数列表的定义
            //      在 MethodVariant 中创建每个方法对应的TS类型名参数列表, 完全相同的不再输出
            var prefix = "";

            // if (method.Name.StartsWith("op_"))
            if (bindingInfo is OperatorBindingInfo)
            {
                prefix += "// js_op_overloading: ";
            }
            if (method.IsStatic && !isExtension)
            {
                prefix += "static ";
            }
            string tsMethodRename;

            if (this.cg.bindingManager.GetTSMethodRename(method, out tsMethodRename))
            {
                this.cg.tsDeclare.Append($"{prefix}{tsMethodRename}(");
            }
            else
            {
                this.cg.tsDeclare.Append($"{prefix}{bindingInfo.regName}(");
            }

            if (isRaw)
            {
                this.cg.tsDeclare.AppendL("...uncertain: any[]): any /* uncertain */");
                this.cg.tsDeclare.AppendLine();
            }
            else
            {
                var parameters = method.GetParameters();
                if (isExtension)
                {
                    ArrayUtility.RemoveAt(ref parameters, 0);
                }

                // 剔除 out 参数
                for (int i = 0, len = parameters.Length; i < len;)
                {
                    var parameter = parameters[i];
                    if (parameter.IsOut)
                    {
                        ArrayUtility.RemoveAt(ref parameters, i);
                        len--;
                        refParameters.Add(parameter);
                    }
                    else
                    {
                        if (parameter.ParameterType.IsByRef)
                        {
                            refParameters.Add(parameter);
                        }
                        i++;
                    }
                }

                for (int i = 0, len = parameters.Length; i < len; i++)
                {
                    var parameter        = parameters[i];
                    var parameter_prefix = "";
                    var parameterType    = parameter.ParameterType;

                    if (parameter.IsDefined(typeof(ParamArrayAttribute), false) && i == parameters.Length - 1)
                    {
                        var elementType      = parameterType.GetElementType();
                        var elementTS        = this.cg.bindingManager.GetTSTypeFullName(elementType);
                        var parameterVarName = BindingManager.GetTSVariable(parameter);
                        this.cg.tsDeclare.AppendL($"{parameter_prefix}...{parameterVarName}: {elementTS}[]");
                    }
                    else
                    {
                        var parameterTS      = this.cg.bindingManager.GetTSTypeFullName(parameter);
                        var parameterVarName = BindingManager.GetTSVariable(parameter);
                        this.cg.tsDeclare.AppendL($"{parameter_prefix}{parameterVarName}: {parameterTS}");
                    }
                    if (i != parameters.Length - 1)
                    {
                        this.cg.tsDeclare.AppendL(", ");
                    }
                }
                this.cg.tsDeclare.AppendL($")");
                WriteTSReturn(method, refParameters);
            }
            return(refParameters);
        }
Esempio n. 3
0
        // 写入返回类型声明
        protected virtual void WriteTSReturn(T method, List <ParameterInfo> returnParameters)
        {
            var returnType = GetReturnType(method);
            var count      = returnParameters.Count;

            if (returnType != null && returnType != typeof(void))
            {
                if (count != 0)
                {
                    this.cg.tsDeclare.AppendL(": { ");

                    var returnTypeTS  = this.cg.bindingManager.GetTSReturnTypeFullName(returnType);
                    var returnVarName = BindingManager.GetTSVariable("return");
                    this.cg.tsDeclare.AppendL($"\"{returnVarName}\": {returnTypeTS}");

                    for (var i = 0; i < count; i++)
                    {
                        var rp   = returnParameters[i];
                        var name = BindingManager.GetTSVariable(rp.Name);
                        var ts   = this.cg.bindingManager.GetTSTypeFullName(rp.ParameterType);
                        if (i != count - 1)
                        {
                            this.cg.tsDeclare.AppendL($", \"{name}\": {ts}");
                        }
                        else
                        {
                            this.cg.tsDeclare.AppendL($", \"{name}\": {ts}");
                        }
                    }
                    this.cg.tsDeclare.AppendL(" }");
                    this.cg.tsDeclare.AppendLine();
                }
                else
                {
                    var returnTypeTS = this.cg.bindingManager.GetTSReturnTypeFullName(returnType);
                    this.cg.tsDeclare.AppendL($": {returnTypeTS}");
                    this.cg.tsDeclare.AppendLine();
                }
            }
            else
            {
                if (count != 0)
                {
                    this.cg.tsDeclare.AppendL(": { ");
                    for (var i = 0; i < count; i++)
                    {
                        var rp   = returnParameters[i];
                        var name = rp.Name;
                        var ts   = this.cg.bindingManager.GetTSTypeFullName(rp.ParameterType);
                        if (i != count - 1)
                        {
                            this.cg.tsDeclare.AppendL($"\"{name}\": {ts}, ");
                        }
                        else
                        {
                            this.cg.tsDeclare.AppendL($"\"{name}\": {ts}");
                        }
                    }
                    this.cg.tsDeclare.AppendL(" }");
                    this.cg.tsDeclare.AppendLine();
                }
                else
                {
                    this.cg.tsDeclare.AppendLine();
                }
            }
        }
Esempio n. 4
0
        // 收集所有 字段,属性,方法
        public void Collect()
        {
            var bindingFlags = Binding.DynamicType.PublicFlags;
            var fields       = type.GetFields(bindingFlags);

            foreach (var field in fields)
            {
                if (field.IsSpecialName || field.Name.StartsWith("_JSFIX_"))
                {
                    bindingManager.Info("skip special field: {0}", field.Name);
                    continue;
                }

                if (field.FieldType.IsPointer)
                {
                    bindingManager.Info("skip pointer field: {0}", field.Name);
                    continue;
                }

                if (field.IsDefined(typeof(JSOmitAttribute), false))
                {
                    bindingManager.Info("skip omitted field: {0}", field.Name);
                    continue;
                }

                if (field.IsDefined(typeof(ObsoleteAttribute), false))
                {
                    bindingManager.Info("skip obsolete field: {0}", field.Name);
                    continue;
                }

                if (transform != null && transform.IsMemberBlocked(field.Name))
                {
                    bindingManager.Info("skip blocked field: {0}", field.Name);
                    continue;
                }

                AddField(field);
            }

            var events = type.GetEvents(bindingFlags);

            foreach (var evt in events)
            {
                if (evt.IsSpecialName)
                {
                    bindingManager.Info("skip special event: {0}", evt.Name);
                    continue;
                }

                if (evt.EventHandlerType.IsPointer)
                {
                    bindingManager.Info("skip pointer event: {0}", evt.Name);
                    continue;
                }

                if (evt.IsDefined(typeof(ObsoleteAttribute), false))
                {
                    bindingManager.Info("skip obsolete event: {0}", evt.Name);
                    continue;
                }

                if (evt.IsDefined(typeof(JSOmitAttribute), false))
                {
                    bindingManager.Info("skip omitted event: {0}", evt.Name);
                    continue;
                }

                if (transform != null && transform.IsMemberBlocked(evt.Name))
                {
                    bindingManager.Info("skip blocked event: {0}", evt.Name);
                    continue;
                }

                AddEvent(evt);
            }

            var properties = type.GetProperties(bindingFlags);

            foreach (var property in properties)
            {
                if (property.IsSpecialName)
                {
                    bindingManager.Info("skip special property: {0}", property.Name);
                    continue;
                }

                if (property.PropertyType.IsPointer)
                {
                    bindingManager.Info("skip pointer property: {0}", property.Name);
                    continue;
                }

                if (property.IsDefined(typeof(JSOmitAttribute), false))
                {
                    bindingManager.Info("skip omitted property: {0}", property.Name);
                    continue;
                }

                if (property.IsDefined(typeof(ObsoleteAttribute), false))
                {
                    bindingManager.Info("skip obsolete property: {0}", property.Name);
                    continue;
                }

                if (transform != null && transform.IsMemberBlocked(property.Name))
                {
                    bindingManager.Info("skip blocked property: {0}", property.Name);
                    continue;
                }

                //NOTE: 索引访问
                if (property.Name == "Item")
                {
                    if (property.CanRead && property.GetMethod != null)
                    {
                        if (BindingManager.IsUnsupported(property.GetMethod))
                        {
                            bindingManager.Info("skip unsupported get-method: {0}", property.GetMethod);
                            continue;
                        }

                        AddMethod(property.GetMethod, true, "$GetValue");
                    }

                    if (property.CanWrite && property.SetMethod != null)
                    {
                        if (BindingManager.IsUnsupported(property.SetMethod))
                        {
                            bindingManager.Info("skip unsupported set-method: {0}", property.SetMethod);
                            continue;
                        }

                        AddMethod(property.SetMethod, true, "$SetValue");
                    }

                    // bindingManager.Info("skip indexer property: {0}", property.Name);
                    continue;
                }

                AddProperty(property);
            }

            if (!type.IsAbstract)
            {
                var constructors = type.GetConstructors();
                foreach (var constructor in constructors)
                {
                    if (constructor.IsDefined(typeof(JSOmitAttribute), false))
                    {
                        bindingManager.Info("skip omitted constructor: {0}", constructor);
                        continue;
                    }

                    if (constructor.IsDefined(typeof(ObsoleteAttribute), false))
                    {
                        bindingManager.Info("skip obsolete constructor: {0}", constructor);
                        continue;
                    }

                    if (BindingManager.ContainsPointer(constructor))
                    {
                        bindingManager.Info("skip pointer-param constructor: {0}", constructor);
                        continue;
                    }

                    if (BindingManager.ContainsByRefParameters(constructor))
                    {
                        bindingManager.Info("skip byref-param constructor: {0}", constructor);
                        continue;
                    }

                    AddConstructor(constructor);
                }
            }

            CollectMethods(type.GetMethods(bindingFlags));
            CollectMethods(bindingManager.GetTypeTransform(type).extensionMethods);
        }
Esempio n. 5
0
        public void AddMethod(MethodInfo methodInfo, bool isIndexer, string renameRegName)
        {
            if (this.transform != null)
            {
                if (this.transform.IsBlocked(methodInfo))
                {
                    bindingManager.Info("skip blocked method: {0}", methodInfo.Name);
                    return;
                }
            }

            var isExtension = BindingManager.IsExtensionMethod(methodInfo);
            var isStatic    = methodInfo.IsStatic && !isExtension;
            var methodName  = TypeBindingInfo.GetNamingAttribute(methodInfo);

            if (IsSupportedOperators(methodInfo))
            {
                var parameters    = methodInfo.GetParameters();
                var declaringType = methodInfo.DeclaringType;
                OperatorBindingInfo operatorBindingInfo = null;
                switch (methodName)
                {
                case "op_LessThan":
                    if (parameters.Length == 2)
                    {
                        if (parameters[0].ParameterType == declaringType && parameters[1].ParameterType == declaringType)
                        {
                            operatorBindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "<", "<", 2);
                        }
                    }
                    break;

                case "op_Addition":
                    if (parameters.Length == 2)
                    {
                        if (parameters[0].ParameterType == declaringType && parameters[1].ParameterType == declaringType)
                        {
                            operatorBindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "+", "+", 2);
                        }
                    }
                    break;

                case "op_Subtraction":
                    if (parameters.Length == 2)
                    {
                        if (parameters[0].ParameterType == declaringType && parameters[1].ParameterType == declaringType)
                        {
                            operatorBindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "-", "-", 2);
                        }
                    }
                    break;

                case "op_Equality":
                    if (parameters.Length == 2)
                    {
                        if (parameters[0].ParameterType == declaringType && parameters[1].ParameterType == declaringType)
                        {
                            operatorBindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "==", "==", 2);
                        }
                    }
                    break;

                case "op_Multiply":
                    if (parameters.Length == 2)
                    {
                        var op0 = bindingManager.GetExportedType(parameters[0].ParameterType);
                        var op1 = bindingManager.GetExportedType(parameters[1].ParameterType);
                        if (op0 != null && op1 != null)
                        {
                            var bindingName = methodName + "_" + op0.name + "_" + op1.name;
                            operatorBindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, bindingName, "*", "*", 2);
                        }
                    }
                    break;

                case "op_Division":
                    if (parameters.Length == 2)
                    {
                        var op0 = bindingManager.GetExportedType(parameters[0].ParameterType);
                        var op1 = bindingManager.GetExportedType(parameters[1].ParameterType);
                        if (op0 != null && op1 != null)
                        {
                            var bindingName = methodName + "_" + op0.name + "_" + op1.name;
                            operatorBindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, bindingName, "/", "/", 2);
                        }
                    }
                    break;

                case "op_UnaryNegation":
                {
                    operatorBindingInfo = new OperatorBindingInfo(methodInfo, isExtension, isStatic, methodName, "neg", "-", 1);
                }
                break;
                }

                if (operatorBindingInfo != null)
                {
                    operators.Add(operatorBindingInfo);
                    CollectDelegate(methodInfo);
                    bindingManager.Info("[AddOperator] {0}.{1}", type, methodInfo);
                    return;
                }

                // fallback to normal method binding
            }

            var group = isStatic ? staticMethods : methods;
            MethodBindingInfo methodBindingInfo;

            if (!group.TryGetValue(methodName, out methodBindingInfo))
            {
                methodBindingInfo = new MethodBindingInfo(isIndexer, isStatic, methodName, renameRegName ?? methodName);
                group.Add(methodName, methodBindingInfo);
            }
            if (!methodBindingInfo.Add(methodInfo, isExtension))
            {
                bindingManager.Info("fail to add method: {0}", methodInfo.Name);
                return;
            }

            CollectDelegate(methodInfo);
            bindingManager.Info("[AddMethod] {0}.{1}", type, methodInfo);
        }
Esempio n. 6
0
        public override void Dispose()
        {
            using (new RegFuncCodeGen(cg))
            {
                using (new RegFuncNamespaceCodeGen(cg, typeBindingInfo))
                {
                    var constructor = typeBindingInfo.constructors.available ? typeBindingInfo.constructors.name : "JSApi.class_private_ctor";
                    if (!typeBindingInfo.constructors.available && !typeBindingInfo.type.IsAbstract)
                    {
                        if (typeBindingInfo.type.IsSubclassOf(typeof(Component)))
                        {
                            // 因为 ts 泛型约束需要 new() 形式, 所以在定义中产生一个 public 定义
                            // 例如: GetComponent<T extends Component>(type: { new(): T }): T
                            cg.tsDeclare.AppendLine("/*protected*/ constructor()");
                        }
                        else
                        {
                            cg.tsDeclare.AppendLine("protected constructor()");
                        }
                    }
                    cg.cs.AppendLine("var cls = ns.CreateClass(\"{0}\", typeof({1}), {2});",
                                     typeBindingInfo.jsName,
                                     this.cg.bindingManager.GetCSTypeFullName(typeBindingInfo.type),
                                     constructor);

                    // 运算符
                    foreach (var operatorBindingInfo in typeBindingInfo.operators)
                    {
                        var    regName       = operatorBindingInfo.regName;
                        var    funcName      = operatorBindingInfo.name;
                        var    parameters    = operatorBindingInfo.methodInfo.GetParameters();
                        var    declaringType = operatorBindingInfo.methodInfo.DeclaringType;
                        string redirect;
                        if (this.typeBindingInfo.transform != null && this.typeBindingInfo.transform.TryRedirectMethod(regName, out redirect))
                        {
                            funcName = redirect;
                        }

                        do
                        {
                            if (parameters.Length == 2)
                            {
                                if (parameters[0].ParameterType != declaringType)
                                {
                                    var leftType = typeBindingInfo.bindingManager.GetCSTypeFullName(parameters[0].ParameterType);
                                    cg.cs.AppendLine("cls.AddLeftOperator(\"{0}\", {1}, {2}, typeof({3}));", regName, funcName, operatorBindingInfo.length, leftType);
                                    break;
                                }
                                else if (parameters[1].ParameterType != declaringType)
                                {
                                    var rightType = typeBindingInfo.bindingManager.GetCSTypeFullName(parameters[1].ParameterType);
                                    cg.cs.AppendLine("cls.AddRightOperator(\"{0}\", {1}, {2}, typeof({3}));", regName, funcName, operatorBindingInfo.length, rightType);
                                    break;
                                }
                            }

                            cg.cs.AppendLine("cls.AddSelfOperator(\"{0}\", {1}, {2});", regName, funcName, operatorBindingInfo.length);
                        } while (false);
                    }

                    // 非静态方法
                    foreach (var kv in typeBindingInfo.methods)
                    {
                        var    regName  = kv.Value.regName;
                        var    funcName = kv.Value.name;
                        string redirect;
                        if (this.typeBindingInfo.transform != null && this.typeBindingInfo.transform.TryRedirectMethod(regName, out redirect))
                        {
                            funcName = redirect;
                        }

                        if (typeBindingInfo.bindingManager.prefs.optToString && regName == "ToString")
                        {
                            cg.cs.AppendLine("cls.AddMethod(false, \"{0}\", {1});", "toString", funcName);
                        }
                        else
                        {
                            cg.cs.AppendLine("cls.AddMethod(false, \"{0}\", {1});", regName, funcName);
                        }
                    }

                    // 静态方法
                    foreach (var kv in typeBindingInfo.staticMethods)
                    {
                        var    regName  = kv.Value.regName;
                        var    funcName = kv.Value.name;
                        string redirect;
                        if (this.typeBindingInfo.transform != null && this.typeBindingInfo.transform.TryRedirectMethod(regName, out redirect))
                        {
                            funcName = redirect;
                        }
                        cg.cs.AppendLine("cls.AddMethod(true, \"{0}\", {1});", regName, funcName);
                    }

                    // 属性
                    foreach (var kv in typeBindingInfo.properties)
                    {
                        var bindingInfo = kv.Value;
                        if (bindingInfo.staticPair.IsValid())
                        {
                            var tsPropertyVar = BindingManager.GetTSVariable(bindingInfo.regName);
                            cg.cs.AppendLine("cls.AddProperty(true, \"{0}\", {1}, {2});",
                                             tsPropertyVar,
                                             bindingInfo.staticPair.getterName != null ? bindingInfo.staticPair.getterName : "null",
                                             bindingInfo.staticPair.setterName != null ? bindingInfo.staticPair.setterName : "null");

                            var tsPropertyPrefix = "static ";
                            if (bindingInfo.staticPair.setterName == null)
                            {
                                tsPropertyPrefix += "readonly ";
                            }
                            var tsPropertyType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.propertyInfo.PropertyType);
                            cg.AppendJSDoc(bindingInfo.propertyInfo);
                            cg.tsDeclare.AppendLine($"{tsPropertyPrefix}{tsPropertyVar}: {tsPropertyType}");
                        }

                        if (bindingInfo.instancePair.IsValid())
                        {
                            var tsPropertyVar = BindingManager.GetTSVariable(bindingInfo.regName);
                            cg.cs.AppendLine("cls.AddProperty(false, \"{0}\", {1}, {2});",
                                             tsPropertyVar,
                                             bindingInfo.instancePair.getterName != null ? bindingInfo.instancePair.getterName : "null",
                                             bindingInfo.instancePair.setterName != null ? bindingInfo.instancePair.setterName : "null");

                            var tsPropertyPrefix = "";
                            if (bindingInfo.instancePair.setterName == null)
                            {
                                tsPropertyPrefix += "readonly ";
                            }
                            var tsPropertyType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.propertyInfo.PropertyType);
                            cg.AppendJSDoc(bindingInfo.propertyInfo);
                            cg.tsDeclare.AppendLine($"{tsPropertyPrefix}{tsPropertyVar}: {tsPropertyType}");
                        }
                    }
                    foreach (var kv in typeBindingInfo.fields)
                    {
                        var bindingInfo = kv.Value;
                        var bStatic     = bindingInfo.isStatic;
                        var tsFieldVar  = BindingManager.GetTSVariable(bindingInfo.regName);
                        if (bindingInfo.constantValue != null)
                        {
                            var cv = bindingInfo.constantValue;
                            cg.cs.AppendLine($"cls.AddConstValue(\"{tsFieldVar}\", {cv});");
                        }
                        else
                        {
                            cg.cs.AppendLine("cls.AddField({0}, \"{1}\", {2}, {3});",
                                             bStatic ? "true" : "false",
                                             tsFieldVar,
                                             bindingInfo.getterName != null ? bindingInfo.getterName : "null",
                                             bindingInfo.setterName != null ? bindingInfo.setterName : "null");
                        }
                        var tsFieldPrefix = bStatic ? "static " : "";
                        if (bindingInfo.setterName == null)
                        {
                            tsFieldPrefix += "readonly ";
                        }
                        var tsFieldType = this.cg.bindingManager.GetTSTypeFullName(bindingInfo.fieldInfo.FieldType);
                        cg.AppendJSDoc(bindingInfo.fieldInfo);
                        cg.tsDeclare.AppendLine($"{tsFieldPrefix}{tsFieldVar}: {tsFieldType}");
                    }
                    foreach (var kv in typeBindingInfo.events)
                    {
                        var eventBindingInfo = kv.Value;
                        var bStatic          = eventBindingInfo.isStatic;
                        //NOTE: 静态事件在绑定过程直接定义, 非静态事件推迟到构造时直接赋值创建
                        var tsFieldVar    = BindingManager.GetTSVariable(eventBindingInfo.regName);
                        var tsFieldType   = this.cg.bindingManager.GetTSTypeFullName(eventBindingInfo.eventInfo.EventHandlerType);
                        var tsFieldPrefix = "";
                        if (bStatic)
                        {
                            tsFieldPrefix += "static ";
                            cg.cs.AppendLine($"cls.AddEvent(true, \"{tsFieldVar}\", {eventBindingInfo.adderName}, {eventBindingInfo.removerName});");
                        }
                        else
                        {
                            cg.cs.AppendLine($"cls.AddProperty(false, \"{tsFieldVar}\", {eventBindingInfo.proxyName}, null);");
                        }
                        cg.tsDeclare.AppendLine($"{tsFieldPrefix}{tsFieldVar}: {CodeGenerator.NamespaceOfScriptTypes}.event<{tsFieldType}>");
                    }
                    cg.cs.AppendLine("cls.Close();");
                }
            }
            base.Dispose();

            this.cg.tsDeclare.DecTabLevel();
            this.cg.tsDeclare.AppendLine("}");
        }