UI Modernization Part 1: Using Existing C# DTO Classes in Typescript Projects
As software trends keep changing, it is inevitable to map definitions from one language to another. Therefore, it would be wise to choose or create tools that can speed up the migration process. In these article series, I will explain how we can map C# WPF projects to Angular Typescript projects.
This first article is about using existing C# DTO classes in Typescript projects.
Why to develop a tool ?
Even though there are different tools for C# to Typescript conversion [1], each system has its own customizations. That’s why, it is better to create a tool that will cover most of the demands for current system.
Roadmap to conversion
- Decide the input
- Extract the features like class names, properties, enums, interfaces, default values etc.
- Map onto new language
- Show the output
What is the input ?
First thing first, we should decide the input.
- Source Codes
- Compiled Codes
Source codes are human-readable. However, human will not convert the DTOs. The tool will do it for us. Therefore, if you choose source code as input, you will need a parser to extract features like class names, enums, interfaces, class’ properties and values. Then, you will decide how to map.
Compiled codes are usually not human-readable. That’s why using or writing your own lexical analyzer or parser will probably not make sense. Compiled codes are created to be used in runtime. That’s why if you choose compiled codes as input, the tool does not need a parser cuz it will use compiled codes just like external compiled codes. In other words, it will load compiled codes in runtime and used it as usual.
As DTO classes contains only primitive types and not complex things in VakıfBank system, we decided to use compiled codes as input. Basically, we will not need a parser and what we need is just reflection [2].
How to extract features ?
Well, as I mentioned in previous section, we will use reflection to extract features. Let me show you how we did it.
First, we should load assembly in runtime.
Then, we should extract classes, enums and interfaces.
After this step, we will get fields,properties and methods from them.
For enums;
For Interfaces;
Unlike the enums and interfaces, class’ properties can be in different types. That’s why we need a data type mapper.
How to map ?
Since we will map onto Typescript language, it will be sufficient to know typescript equivalents of primitive types in C# language. A simple dictionary that stores equivalents will be useful.
How to prepare properties ?
As we mentioned in previous section, class type has properties and each property could have different type. That’s why we will use DataTypeMapper.
So let’s continue with class conversion.
For classes, we get fields and properties with mapping.
How to produce output ?
After the end of extraction and mapping process, we can finally produce the output. All we have to do is defining all classes, properties and enums with new language’s syntax. Therefore, we created string template writer method and loop through lists we got in previous sections to show the output.
Here is the output
Is that all ? Any Challenges ?
Well, in this section I will talk about the challenges and problems we had.
The first issue was .dll files had dependencies from different libraries. .NET wants to load an assembly with all dependencies. Hence, we used AssemblyResolved event to load missing ones.
The other problem was related with .NET behavior on runtime as well. Once the assembly is loaded, .NET stores it in current AppDomain. However, when a developer changes codes and loads the new compiled codes with same name, .NET uses the first loaded one. We solved the problem by creating AppDomain in every time the tool loads assembly. After that, we made converter to unload new created AppDomain.
Here is a code snippet to show AssemblyResolve event and AppDomains usage.
The last problem was classes had dependencies from enums and different classes. That’s why we had to find the dependencies and convert them as well. Therefore, we found all properties’ types with their namespace. If it does not match up the current class namespace, we can reckon that this causes dependencies. Thus, we should add dependencies to output printer.
Future work
Enterprise systems contain many projects developed in various languages and it will always be useful to use utility programmes . In next article, I will write about screen(WPF, ViewModel to HTML, Typescript) conversions.