Exemplo n.º 1
0
        string MapComplexType(Type type)
        {
            if (_processedTypes.TryGetValue(type, out var name))
            {
                return(name);
            }

            name = _opts.DtoClassNamingPolicy(type);
            name = name.Split('`')[0];
            if (_usedNames.Contains(name))
            {
                throw new InvalidProgramException(name + " is already in use");
            }
            _processedTypes[type] = name;

            var code     = new TypescriptCodeBuilder();
            var typeInfo = type.GetTypeInfo();

            if (typeInfo.IsInterface || typeInfo.IsClass)
            {
                var tsName = name;
                if (typeInfo.IsGenericTypeDefinition)
                {
                    tsName = name +
                             "<" + string.Join(",", type.GetGenericArguments().Select(a => a.Name)) + ">";
                }

                code.BeginInterface(tsName);
                foreach (var p in type.GetProperties())
                {
                    var typeName = MapType(p.PropertyType);
                    code.AppendInterfaceProperty(_opts.DtoFieldNamingPolicy(p.Name), typeName);
                }

                code.End();
            }
            else if (typeInfo.IsEnum)
            {
                code.BeginEnum(name);
                foreach (var en in Enum.GetNames(type))
                {
                    code.AppendEnumValue(en, en);
                }
                code.End();
            }
            else
            {
                throw new InvalidProgramException($"Don't know how to convert {type.FullName} to typescript");
            }

            _builder.AppendLine(code.ToString());
            return(name);
        }
Exemplo n.º 2
0
        public static string GenerateGlueCode(TypescriptGenerationOptions opts, IEnumerable <Type> types)
        {
            var ctx  = new TypescriptTypeMapping(opts);
            var code = new TypescriptCodeBuilder();

            var ctor            = new List <string>();
            var fields          = new List <string>();
            var interfaceFields = new List <string>();


            foreach (var type in types)
            {
                var proxyClassName     = "CoreRpcProxyFor" + type.Name;
                var proxyFieldName     = opts.ApiFieldNamingPolicy(type);
                var proxyInterfaceName = "I" + proxyClassName;
                foreach (var iface in new[] { true, false })
                {
                    if (iface)
                    {
                        code.BeginInterface(proxyInterfaceName);
                    }
                    else
                    {
                        code.BeginClass(proxyClassName + " implements " + proxyInterfaceName);
                        code.AppendLines(
                            $"private parent: {opts.ClassName};",
                            $"constructor (parent: {opts.ClassName}){{this.parent = parent;}}"
                            );
                    }

                    var target = opts.TargetNameExtractor.GetTargetName(type);
                    foreach (var m in type.GetMethods())
                    {
                        if (m.DeclaringType == typeof(System.Object))
                        {
                            continue;
                        }
                        var sig = Convert.ToBase64String(opts.Binder.GetMethodSignature(m));

                        code.BeginMethod(opts.ApiMethodNamingPolicy(m.Name), iface ? (bool?)null : true);
                        var names = new List <string>();
                        foreach (var p in m.GetParameters())
                        {
                            code.AppendMethodParameter(p.Name, ctx.MapType(p.ParameterType));
                            names.Add(p.Name);
                        }

                        var returnType = m.ReturnType;
                        if (returnType == typeof(Task))
                        {
                            returnType = typeof(void);
                        }
                        else if (returnType.IsConstructedGenericType &&
                                 returnType.GetGenericTypeDefinition() == typeof(Task <>))
                        {
                            returnType = returnType.GetGenericArguments()[0];
                        }
                        var returnTypeName = ctx.MapType(returnType);
                        code.AppendMethodReturnValue("Promise<" + returnTypeName + ">");
                        if (iface)
                        {
                            code.AppendSemicolon();
                        }
                        else
                        {
                            code.BeginBody();
                            var req =
                                $"{{Target: '{target}', MethodSignature: '{sig}', Arguments: [{string.Join(",", names)}] }}";
                            code.AppendLine($"return this.parent.send<{returnTypeName}>({req});");
                            code.End();
                        }
                    }

                    code.End();
                }

                interfaceFields.Add($"{proxyFieldName} : " + proxyInterfaceName + ";");
                fields.Add($"{proxyFieldName} : " + proxyClassName + ";");
                ctor.Add($"this.{proxyFieldName} = new {proxyClassName}(this);");
            }

            var resultFieldName    = "Result";
            var exceptionFieldName = "Exception";

            code.BeginInterface("I" + opts.ClassName);
            code.AppendLines(interfaceFields.ToArray());
            code.End();

            code.BeginClass(opts.ClassName + " implements I" + opts.ClassName);
            code.AppendLines(
                "private baseUrl: string;",
                "private fetch: (url: string, init: RequestInit) => Promise<Response>;",

                "constructor(baseUrl : string, customFetch?: (url: string, init: RequestInit) => Promise<Response>) {",
                "this.baseUrl = baseUrl;",
                "if(customFetch) this.fetch = customFetch; else this.fetch =  (r, i) => fetch(r, i);"
                );
            code.AppendLines(ctor.ToArray());
            code.AppendLine("}");


            code.AppendLines(
                "public send<T>(request: any) : Promise<T>{",
                "return this.fetch(this.baseUrl, {method: 'post', body: JSON.stringify(request)})",
                "    .then(response => {",
                "        if (!response.ok)",
                "            throw new Error(response.statusText);",
                "         return response.json();",
                "    }).then(jr => {",
                $"        const r = <{{{resultFieldName}?: T, {exceptionFieldName}?: string}}>jr;",
                $"        if(r.{exceptionFieldName}) throw r.{exceptionFieldName};",
                $"        return r.{resultFieldName}!;",
                "    });",
                "}"
                );
            code.AppendLines(fields.ToArray());
            code.End();

            return((ctx + "\n" + code).Replace("\r\n", "\n"));
        }