using System.Text; using System.Collections.Generic; using System; using System.Linq; namespace ser; public abstract class CodeGenerator { protected StringBuilder _sb = new StringBuilder(); protected int _indent = 0; protected TypeStructureAnalyzer _analyzer; protected CodeGenConfig _config; protected HashSet _generatedTypes = new(); // Track to avoid re-generating public CodeGenerator( CodeGenConfig config ) { _config = config; _analyzer = new TypeStructureAnalyzer( config ); } // Main entry point public string Generate( Type type, string ns = "GeneratedCode" ) { _sb.Clear(); WriteLine( "using System;" ); WriteLine( "using System.Collections.Generic;" ); WriteLine( "using System.Linq;" ); WriteLine( "" ); WriteLine( $"namespace {ns};" ); WriteLine( "" ); GenerateForType( type ); return _sb.ToString(); } // Core generation logic - needs to be recursive for dependencies protected virtual void GenerateForType( Type type ) { if( type == null || !CanGenerateFor( type ) || _generatedTypes.Contains( type ) ) return; _generatedTypes.Add( type ); var info = _analyzer.Get( type ); // Generate dependencies first foreach( var member in info.Members ) { GenerateForType( member.Type ); if( member.IsCollection && member.CollectionElementType != null ) { GenerateForType( member.CollectionElementType ); } } // Generate the actual code GenerateClassHeader( info ); BeginBlock(); GenerateClassBody( info ); EndBlock(); } // Abstract methods to be implemented by specific generators protected abstract void GenerateClassHeader( TypeStructureInfo info ); protected abstract void GenerateClassBody( TypeStructureInfo info ); protected abstract bool CanGenerateFor( Type type ); // Check if we should generate for this type // Helper methods protected void WriteLine( string line = "" ) => _sb.AppendLine( new string( '\t', _indent ) + line ); protected void BeginBlock() { WriteLine( "{" ); _indent++; } protected void EndBlock() { _indent--; WriteLine( "}" ); } protected string GetTypeName( Type t ) => t.IsGenericType ? $"{t.Name.Split( '`' )[0]}<{string.Join( ", ", t.GetGenericArguments().Select( GetTypeName ) )}>" : t.Name; // Basic handling, needs improvement for full names/namespaces }