日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

typescript get方法_.NET手撸绘制TypeScript类图——上篇

發布時間:2025/3/12 asp.net 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 typescript get方法_.NET手撸绘制TypeScript类图——上篇 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

.NET手擼繪制TypeScript類圖——上篇

近年來隨著交互界面的精細化,TypeScript越來越流行,前端的設計也越來復雜,而類圖正是用簡單的箭頭和方塊,反映對象與對象之間關系/依賴的好方式。許多工具都能生成C#類圖,有些工具也能生成TypeScript類圖,如tsuml,但存在一些局限性。

我們都是.NET開發,為啥不干脆就用.NET擼一個TypeScript類圖呢?

說干就干!為了搞到類圖,一共分兩步走:

  • 解析.ts文件,生成抽象語法樹(AST),并轉換為簡單的類、屬性、方法等對象
  • 將這個對象繪制出來
  • 本文將分上下兩部分,上篇將介紹我移植的一個.NET Standard 2.0的TypeScript解析庫,下篇將介紹如何將AST轉換為真正的圖,并實現一些基本的交互。

    .ts文件生成抽象語法樹

    正常來說編譯原理挺難的,但好在有人趕在了我的前頭 。

    TypeScript解析庫

    我在Github上找到了一個叫TypeScriptAST的項目,它剛好就能將.ts文件轉換為AST。但它僅提供了.NET Framework版本。我看了一下實現方式,它是從微軟官方的TypeScript倉庫按源代碼翻譯的。其中Parse.cs高達近8000行代碼,能把如此巨大的工作翻譯完成,可見作者花了不少時間。

    我拿了過來,稍微改造了一下,移植到了.NET Core。NuGet包地址為:

    https://www.nuget.org/packages/Sdcb.TypeScriptAST/

    我移植的這個版本源代碼也開放到了Github,使用相同的Apache-2.0協議開源,開源項目鏈接如下:

    https://github.com/sdcb/TypeScriptAST

    雖然不知道是不是第一個移植的,但可以確定的是今后.NET Core也能解析TypeScript了:)

    注意:官方沒有提供TypeScript的.NET解析工具,也沒建議用.NET,使用ts解析是正常做法,官方的包用起來顯然也更有自信——但這就是騷操作,不挑戰一下怎么知道極限在哪呢?

    簡單使用

    假如有如下TypeScript代碼:

    class Class1 {td: number = 3;ts: string = 'hello';doWork(): string {return `${3+this.td}-${this.ts}`;} }var tc = new Class1();

    我們可以使用TypeScriptAST的類進行分析,只需使用TypeScriptAST類:

    var ast = new TypeScriptAST(source: tsSourceStringContent);

    該類有許多對象,提供了豐富的解析方式,使用如下代碼,即可將代碼中的類抽出來:

    var classAsts = ast.OfKind(SyntaxKind.ClassDeclaration);

    由于AST中的屬性太多,我們調試時抽重要的顯示出來,并轉換為JSON:

    JsonSerializer.Serialize(classAsts.Select(c => new {c.IdentifierStr,Children = c.Children.Skip(1).Select(x => x.IdentifierStr), }), new JsonSerializerOptions { WriteIndented = true}).Dump();

    結果如下:

    [{"IdentifierStr": "Class1","Children": ["td","ts","doWork"]} ]

    有了這個,我們即可定義一些類型,用于后續繪制AST:

    class ClassDef {public string Name { get; set; }public List<PropertyDef> Properties { get; set; }public List<MethodDef> Methods { get; set; } }class PropertyDef {public string Name { get; set; }public bool IsPublic { get; set; }public bool IsStatic { get; set; }public string Type { get; set; }public override string ToString() => (IsPublic ? "+" : "-") + $" {Name}: " + (String.IsNullOrWhiteSpace(Type) ? "any" : Type); }class MethodDef {public string Name { get; set; }public bool IsPublic { get; set; }public bool IsStatic { get; set; }public List<ParameterDef> Parameters { get; set; }public string ReturnType { get; set; }public override string ToString() => (IsPublic ? "+" : "-")+ $" {Name}({String.Join(", ", Parameters)})"+ (Name == ".ctor" ? "" : $": {ReturnType}"); }class ParameterDef {public string Name { get; set; }public string Type { get; set; }public override string ToString() => $"{Name}: {Type}"; }

    借助于.NET強大的LINQ,可以將代碼寫得特別精練,最后可以達到“一行代碼*”完成.ts到AST的轉換:

    static Dictionary<string, ClassDef> ParseFiles(IEnumerable<string> files) => files.Select(x => new TypeScriptAST(File.ReadAllText(x), x)).SelectMany(x => x.OfKind(SyntaxKind.ClassDeclaration)).Select(x => new ClassDef{Name = x.OfKind(SyntaxKind.Identifier).FirstOrDefault().GetText(),Properties = x.OfKind(SyntaxKind.PropertyDeclaration).Select(x => new PropertyDef{Name = x.IdentifierStr,IsPublic = x.First.Kind != SyntaxKind.PrivateKeyword,IsStatic = x.OfKind(SyntaxKind.StaticKeyword).Any(),Type = GetType(x),}).ToList(),Methods = x.OfKind(SyntaxKind.Constructor).Concat(x.OfKind(SyntaxKind.MethodDeclaration)).Select(x => new MethodDef{Name = x is ConstructorDeclaration ctor ? ".ctor" : x.IdentifierStr,IsPublic = x.First.Kind != SyntaxKind.PrivateKeyword,IsStatic = x.OfKind(SyntaxKind.StaticKeyword).Any(),Parameters = ((ISignatureDeclaration)x).Parameters.Select(x => new ParameterDef{Name = x.OfKind(SyntaxKind.Identifier).FirstOrDefault().GetText(),Type = GetType(x),}).ToList(),ReturnType = GetReturnType(x),}).ToList(),}).ToDictionary(x => x.Name, v => v);

    兩個函數稍微提取一下,代碼能更精練:

    static string GetReturnType(Node node) => node.Children.OfType<TypeNode>().FirstOrDefault()?.GetText();static string GetType(Node node) => node switch {var x when x.OfKind(SyntaxKind.TypeReference).Any() => x.OfKind(SyntaxKind.TypeReference).First().GetText(),_ => node.Last switch{LiteralExpression literal => literal.Kind.ToString()[..^7].ToLower() switch{"numeric" => "number",var x => x,},var x => x.GetText(),}, };

    使用

    我對這個ShootR項目進行了分析,分析代碼如下:

    ParseFiles(Directory.EnumerateFiles(path: @"C:Usersdotnet-loversourcereposShootRShootRShootRClientShips", "*.ts")).Dump();

    分析結果:

    成功找到了完整的7個類,并將類名、字段名、字段類型、方法名、方法參數和返回值等信息都解析出來了。本還能做得更詳細的,但這些可以留給讀者完成。

    總結

    在本篇我們介紹了如何使用.NET解析TypeScript,并推薦了我移植的一個NuGet包:Sdcb.TypeScriptAST。

    下篇將在這篇的基礎上,介紹如何使用代碼將類圖渲染出來。

    本文所用到的完整代碼,可以在我的Github倉庫中下載: https://github.com/sdcb/blog-data/tree/master/2019/20191113-ts-uml-with-dotnet

    喜歡的朋友 請關注我的微信公眾號:【DotNet騷操作】

    總結

    以上是生活随笔為你收集整理的typescript get方法_.NET手撸绘制TypeScript类图——上篇的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。