I'm continuing my work on automating code generation for AIDBDeveloper, my application development platform, which combines application services, database management and artificial intelligence.
The immediate goal is to migrate the editor of my personal blog, Free Technical Software, a Windows desktop application I developed years ago, to this new platform. But the real work is building automation mechanisms that I can reuse in other projects.
In the previous article, I generated around 11,000 lines of C# and MySQL code using deterministic processes. The result was a database repository, with classes representing the tables in the blog's database schema, their corresponding interfaces, and stored procedures for updating the data.
I only used AI to generate names, descriptions and other texts in English and Spanish. These were incorporated into the code through .NET attributes, which I use extensively to document classes, interfaces, properties and even user interface controls at runtime.
The idea is to let conventional code do everything it can, and reserve AI for the tasks that actually need it.
Increasing the complexity
I've been raising the level of complexity with each article in this series.
In the first one, I automated the localisation of Windows Forms applications. The process added English and Spanish texts to resource files, then modified the designer code to replace literal strings in properties such as AccessibleName, AccessibleDescription and ToolTipText with references to those resources.
In the second article, I moved on to generating code from templates. Apart from C# classes and interfaces, the automation also generated MySQL stored procedures.
Both tasks were relatively straightforward, at least compared with what comes next.
This time, I wanted to generate a component that could be integrated directly into AIDBDeveloper, allowing users to work with the repository through the platform's existing user interface.
That means implementing several predefined interfaces, inheriting from a base class and overriding some of its methods and properties.
Fortunately, my platform already provides the necessary runtime infrastructure, so I was able to generate this component deterministically as well.
Of course, we're still dealing with a standardised database repository. I already know what the generated classes must do and how they must interact with the rest of the application.
The next steps won't be so simple.
When the existing code matters
As I move towards automating the development of more specific components, I'll have to analyse code that already exists.
I'll need to examine classes, interfaces, properties and methods, then present the available implementation options to either the user or an AI.
Some decisions cannot be derived from the code structure alone. But that doesn't mean the entire task has to be handed over to AI.
We can still reduce the amount of information it needs to process, and the number of decisions it has to make.
I'm not trying to demonstrate that everything can be done without artificial intelligence. My objective is to make automation profitable, avoiding unnecessary costs in both tokens and the human time required to supervise and validate the results.
And since I'm working with .NET, why not use Roslyn?
Roslyn enters the picture
Roslyn is Microsoft's open-source compiler platform for C# and Visual Basic .NET. It provides access to the syntactic and semantic structure of source code, allowing applications to analyse and transform it without having to develop their own parsers.
In the video accompanying this article, I show a first, fairly basic use of Roslyn.
My application already uses reflection to discover types and examine their attributes. It can also identify the assembly containing a type and locate the corresponding project.
But finding the actual source file is another matter.
Not every file has the same name as the type it contains. And not every file contains just one type.
Roslyn allows me to locate those declarations in the source files, so the rest of the automation can work directly with them.
Nothing particularly sophisticated, but it saves a lot of work.
And, more importantly, once the mechanism exists, I can reuse it without asking an AI to examine the same source code again and again.
Combining Roslyn and AI
I put this new capability to work in another automation.
My platform contains more than a hundred client and provider interfaces, distributed across several projects. Many of them lack the attributes I use to provide localised names, descriptions and categories.
I could write all those texts manually. Or I could ask an AI to examine the source files and modify them.
Instead, I use reflection to identify the interfaces, Roslyn to locate their declarations and extract the existing XML documentation, and AI to generate only the missing texts.
The changes to the source files and resources are then performed deterministically.
The AI doesn't need to understand the entire solution, and it doesn't need to generate C# code.
I also save its results so that I can repeat the automation without making the same API calls again.
In the video, I show the configuration, execution and results of this process, along with another automation I use to generate Function Calling definitions from .NET interfaces and attributes.
Generating the repository provider
Finally, I return to the original objective: generating the component that connects the repository to AIDBDeveloper.
I reuse the code generation script from the previous article, extending it to generate the necessary metadata, command definitions and provider class.
The resulting repository now contains approximately 13,300 lines of generated code, including 5,500 executable lines.
The new provider component integrates with my existing infrastructure, including component connections, database queries, table selection commands, filtering and sorting.
I demonstrate the result in the video, then examine the generated code in Visual Studio.
The important thing is that the generated component works without requiring manual changes to its code. The process uses existing interfaces, templates, conventions and runtime services that have already been implemented and tested.
The automation doesn't have to invent a new solution every time.
What's next?
The repository is now integrated into AIDBDeveloper. The next challenge is building the actual blog editor.
That will be considerably more specific. I probably won't be able to automate everything, and I'll certainly need to make more decisions based on the existing code.
But I intend to automate as much as possible, particularly the implementation of standard interfaces.
And I suspect Roslyn will do more of the work than AI.
The more I develop this infrastructure, the more I find that the real benefit of AI isn't necessarily having it write the code. It's also having it help me build tools that can do the work without it.
Anyway, here's the video, where I demonstrate the whole process:
I hope you find it interesting, and perhaps useful for your own projects.
Thanks for reading, and see you next time!
