11using DataverseProxyGenerator . Core . Domain ;
22using DataverseProxyGenerator . Core . Generation . Generators ;
3+ using DataverseProxyGenerator . Core . Generation . Mappers ;
34using DataverseProxyGenerator . Core . Templates ;
45
56namespace DataverseProxyGenerator . Core . Generation ;
@@ -40,22 +41,135 @@ public IEnumerable<GeneratedFile> GenerateCode(IEnumerable<TableModel> tables, X
4041 ArgumentNullException . ThrowIfNull ( tables ) ;
4142 ArgumentNullException . ThrowIfNull ( config ) ;
4243
43- var files = new List < GeneratedFile > ( ) ;
44- var version = GetAssemblyVersion ( ) ;
44+ var context = CreateGenerationContext ( config ) ;
45+ var tablesList = tables . ToList ( ) ;
46+ var ( interfaceColumns , tableToInterfaces ) = PrepareIntersectionData ( tablesList , config ) ;
4547
46- var context = new GenerationContext
48+ if ( config . SingleFile )
49+ {
50+ return GenerateSingleFile ( tablesList , interfaceColumns , tableToInterfaces , context ) ;
51+ }
52+
53+ return GenerateMultipleFiles ( tablesList , interfaceColumns , tableToInterfaces , context ) ;
54+ }
55+
56+ private GenerationContext CreateGenerationContext ( XrmGenerationConfig config )
57+ {
58+ return new GenerationContext
4759 {
4860 Namespace = config . NamespaceSetting ?? "DataverseContext" ,
49- Version = version ,
61+ Version = GetAssemblyVersion ( ) ,
5062 Templates = templateProvider ,
5163 ServiceContextName = config . ServiceContextName ,
5264 IntersectMapping = config . IntersectMapping ,
5365 } ;
66+ }
5467
55- var tablesList = tables . ToList ( ) ;
68+ private static ( Dictionary < string , HashSet < ColumnSignature > > InterfaceColumns , Dictionary < string , List < string > > TableToInterfaces )
69+ PrepareIntersectionData ( List < TableModel > tablesList , XrmGenerationConfig config )
70+ {
5671 var tableDict = tablesList . ToDictionary ( t => t . LogicalName , t => t , StringComparer . InvariantCulture ) ;
5772 var tableColumns = BuildTableColumns ( tablesList ) ;
58- var ( interfaceColumns , tableToInterfaces ) = BuildIntersectionData ( config . IntersectMapping , tableDict , tableColumns ) ;
73+ return BuildIntersectionData ( config . IntersectMapping , tableDict , tableColumns ) ;
74+ }
75+
76+ private static IEnumerable < GeneratedFile > GenerateSingleFile (
77+ List < TableModel > tablesList ,
78+ Dictionary < string , HashSet < ColumnSignature > > interfaceColumns ,
79+ Dictionary < string , List < string > > tableToInterfaces ,
80+ GenerationContext context )
81+ {
82+ var templateModel = CreateSingleFileTemplateModel ( tablesList , interfaceColumns , tableToInterfaces , context ) ;
83+
84+ var templateName = "SingleFile.scriban-cs" ;
85+ var template = context . Templates . GetTemplate ( templateName ) ;
86+ var content = template . Render ( templateModel , member => member . Name ) ;
87+
88+ yield return new GeneratedFile ( $ "{ context . ServiceContextName } .cs", content ) ;
89+ }
90+
91+ private static object CreateSingleFileTemplateModel (
92+ List < TableModel > tablesList ,
93+ Dictionary < string , HashSet < ColumnSignature > > interfaceColumns ,
94+ Dictionary < string , List < string > > tableToInterfaces ,
95+ GenerationContext context )
96+ {
97+ var globalOptionsets = GetGlobalOptionsets ( tablesList )
98+ . Select ( enumCol => EnumMapper . MapToTemplateModel ( enumCol , context ) )
99+ . ToList ( ) ;
100+ var interfaces = CreateInterfaceModels ( interfaceColumns , tablesList ) ;
101+
102+ // Add interface lists to tables (without modifying TableModel structure)
103+ var tablesWithInterfaces = tablesList . Select ( table =>
104+ {
105+ var tableInterfaces = tableToInterfaces . TryGetValue ( table . LogicalName , out var ifaces ) ? ifaces : new List < string > ( ) ;
106+ return new
107+ {
108+ table ,
109+ InterfacesList = tableInterfaces ,
110+ } ;
111+ } ) . ToList ( ) ;
112+
113+ // Prepare the template model with correct property names
114+ return new
115+ {
116+ @namespace = context . Namespace ,
117+ version = context . Version ,
118+ serviceContextName = context . ServiceContextName ,
119+ tables = tablesWithInterfaces . Select ( t => new
120+ {
121+ t . table . SchemaName ,
122+ t . table . LogicalName ,
123+ t . table . DisplayName ,
124+ t . table . EntityTypeCode ,
125+ t . table . PrimaryNameAttribute ,
126+ t . table . PrimaryIdAttribute ,
127+ t . table . IsIntersect ,
128+ t . table . Columns ,
129+ t . table . Relationships ,
130+ InterfacesList = t . InterfacesList ,
131+ } ) . ToList ( ) ,
132+ optionsets = globalOptionsets ,
133+ interfaces = interfaces ,
134+ } ;
135+ }
136+
137+ private static List < object > CreateInterfaceModels (
138+ Dictionary < string , HashSet < ColumnSignature > > interfaceColumns ,
139+ List < TableModel > tablesList )
140+ {
141+ return interfaceColumns . Select ( kvp => new
142+ {
143+ Name = kvp . Key ,
144+ Columns = kvp . Value . Select ( sig => FindMatchingColumn ( sig , tablesList ) )
145+ . Where ( c => c != null )
146+ . Select ( col => new
147+ {
148+ SchemaName = Utilities . GenerationUtilities . SanitizeName ( col ! . SchemaName ) ,
149+ col ! . LogicalName ,
150+ col . DisplayName ,
151+ col . Description ,
152+ TypeSignature = Utilities . GenerationUtilities . GetTypeSignature ( col ) ,
153+ } )
154+ . ToList ( ) ,
155+ } ) . ToList < object > ( ) ;
156+ }
157+
158+ private static ColumnModel ? FindMatchingColumn ( ColumnSignature sig , List < TableModel > tablesList )
159+ {
160+ return tablesList . SelectMany ( t => t . Columns )
161+ . FirstOrDefault ( c => c . SchemaName == sig . SchemaName &&
162+ ( c . TypeName == sig . TypeName ||
163+ ( c is EnumColumnModel enumCol && sig . TypeName == $ "EnumColumnModel:{ enumCol . OptionsetName } ") ) ) ;
164+ }
165+
166+ private IEnumerable < GeneratedFile > GenerateMultipleFiles (
167+ List < TableModel > tablesList ,
168+ Dictionary < string , HashSet < ColumnSignature > > interfaceColumns ,
169+ Dictionary < string , List < string > > tableToInterfaces ,
170+ GenerationContext context )
171+ {
172+ var files = new List < GeneratedFile > ( ) ;
59173
60174 // Generate intersection interfaces
61175 foreach ( var kvp in interfaceColumns )
@@ -79,8 +193,8 @@ public IEnumerable<GeneratedFile> GenerateCode(IEnumerable<TableModel> tables, X
79193 }
80194
81195 // Generate enums
82- var globalOptionsets = GetGlobalOptionsets ( tablesList ) ;
83- foreach ( var optionset in globalOptionsets )
196+ var globalOptionsetsMulti = GetGlobalOptionsets ( tablesList ) ;
197+ foreach ( var optionset in globalOptionsetsMulti )
84198 {
85199 files . AddRange ( enumGenerator . Generate ( optionset , context ) ) ;
86200 }
@@ -94,7 +208,8 @@ public IEnumerable<GeneratedFile> GenerateCode(IEnumerable<TableModel> tables, X
94208 files . AddRange ( helperFileGenerator . Generate ( "TableAttributeHelpers" , context ) ) ;
95209 files . AddRange ( helperFileGenerator . Generate ( "ExtendedEntity" , context ) ) ;
96210
97- return files ;
211+ foreach ( var file in files )
212+ yield return file ;
98213 }
99214
100215 private static IEnumerable < EnumColumnModel > GetGlobalOptionsets ( IEnumerable < TableModel > tables )
0 commit comments