CustomDataClassGenerator.cs 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678
  1. //
  2. // Mono.Data.CustomDataClassGenerator
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. // (C)2004 Novell Inc.
  8. //
  9. // API notes are the bottom of the source.
  10. //
  11. // This class is standalone testable (even under MS.NET) when compiled with
  12. // -d:DATACLASS_GENERATOR_STANDALONE .
  13. //
  14. //
  15. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  16. //
  17. // Permission is hereby granted, free of charge, to any person obtaining
  18. // a copy of this software and associated documentation files (the
  19. // "Software"), to deal in the Software without restriction, including
  20. // without limitation the rights to use, copy, modify, merge, publish,
  21. // distribute, sublicense, and/or sell copies of the Software, and to
  22. // permit persons to whom the Software is furnished to do so, subject to
  23. // the following conditions:
  24. //
  25. // The above copyright notice and this permission notice shall be
  26. // included in all copies or substantial portions of the Software.
  27. //
  28. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  29. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  30. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  31. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  32. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  33. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  34. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  35. //
  36. using System;
  37. using System.Xml;
  38. using System.Data;
  39. using System.Collections;
  40. using System.CodeDom;
  41. using System.Globalization;
  42. using System.Text;
  43. using System.CodeDom.Compiler;
  44. using System.ComponentModel;
  45. using System.Runtime.Serialization;
  46. // only for Driver
  47. using Microsoft.CSharp;
  48. using System.IO;
  49. namespace System.Data
  50. {
  51. #if DATACLASS_GENERATOR_STANDALONE
  52. public class Driver
  53. {
  54. public static void Main (string [] args)
  55. {
  56. try {
  57. if (args.Length < 1) {
  58. Console.WriteLine ("mono dsgentest.exe filename");
  59. return;
  60. }
  61. DataSet ds = new DataSet ();
  62. ds.ReadXml (args [0]);
  63. ICodeGenerator gen = new CSharpCodeProvider ().CreateGenerator ();
  64. CodeNamespace cns = new CodeNamespace ("MyNamespace");
  65. TextWriter tw = new StreamWriter (Path.ChangeExtension (args [0], ".ms.cs"), false, Encoding.Default);
  66. TypedDataSetGenerator.Generate (ds, cns, gen);
  67. gen.GenerateCodeFromNamespace (cns, tw, null);
  68. tw.Close ();
  69. cns = new CodeNamespace ("MyNamespace");
  70. tw = new StreamWriter (Path.ChangeExtension (args [0], ".mono.cs"), false, Encoding.Default);
  71. CustomDataClassGenerator.CreateDataSetClasses (ds, cns, gen, null);
  72. gen.GenerateCodeFromNamespace (cns, tw, null);
  73. tw.Close ();
  74. } catch (Exception ex) {
  75. Console.WriteLine (ex);
  76. }
  77. }
  78. }
  79. #endif
  80. #if DATACLASS_GENERATOR_STANDALONE
  81. public class CustomDataClassGenerator
  82. #else
  83. internal class CustomDataClassGenerator
  84. #endif
  85. {
  86. public static void CreateDataSetClasses (DataSet ds,
  87. CodeNamespace cns, ICodeGenerator gen,
  88. ClassGeneratorOptions options)
  89. {
  90. new Generator (ds, cns, gen, options).Run ();
  91. }
  92. public static string MakeSafeName (string name, ICodeGenerator codeGen)
  93. {
  94. if (name == null || codeGen == null)
  95. throw new NullReferenceException ();
  96. name = codeGen.CreateValidIdentifier (name);
  97. if (name.Length == 0)
  98. return "_";
  99. StringBuilder sb = null;
  100. if (!Char.IsLetter (name, 0) && name [0] != '_') {
  101. sb = new StringBuilder ();
  102. sb.Append ('_');
  103. }
  104. int start = 0;
  105. for (int i = 0; i < name.Length; i++) {
  106. if (!Char.IsLetterOrDigit (name, i)) {
  107. if (sb == null)
  108. sb = new StringBuilder ();
  109. sb.Append (name, start, i - start);
  110. sb.Append ('_');
  111. start = i + 1;
  112. }
  113. }
  114. if (sb != null) {
  115. sb.Append (name, start, name.Length - start);
  116. return sb.ToString ();
  117. }
  118. else
  119. return name;
  120. }
  121. }
  122. #if DATACLASS_GENERATOR_STANDALONE
  123. public delegate string CodeNamingMethod (string source, ICodeGenerator gen);
  124. #else
  125. internal delegate string CodeNamingMethod (string source, ICodeGenerator gen);
  126. #endif
  127. #if DATACLASS_GENERATOR_STANDALONE
  128. public class ClassGeneratorOptions
  129. #else
  130. internal class ClassGeneratorOptions
  131. #endif
  132. {
  133. public bool MakeClassesInsideDataSet = true; // default = MS compatible
  134. public CodeNamingMethod CreateDataSetName;
  135. public CodeNamingMethod CreateTableTypeName;
  136. public CodeNamingMethod CreateTableMemberName;
  137. public CodeNamingMethod CreateTableColumnName;
  138. public CodeNamingMethod CreateColumnName;
  139. public CodeNamingMethod CreateRowName;
  140. public CodeNamingMethod CreateRelationName;
  141. public CodeNamingMethod CreateTableDelegateName;
  142. public CodeNamingMethod CreateEventArgsName;
  143. internal string DataSetName (string source, ICodeGenerator gen)
  144. {
  145. if (CreateDataSetName != null)
  146. return CreateDataSetName (source, gen);
  147. else
  148. return CustomDataClassGenerator.MakeSafeName (source, gen);
  149. }
  150. internal string TableTypeName (string source, ICodeGenerator gen)
  151. {
  152. if (CreateTableTypeName != null)
  153. return CreateTableTypeName (source, gen);
  154. else
  155. return CustomDataClassGenerator.MakeSafeName (source, gen) + "DataTable";
  156. }
  157. internal string TableMemberName (string source, ICodeGenerator gen)
  158. {
  159. if (CreateTableMemberName != null)
  160. return CreateTableMemberName (source, gen);
  161. else
  162. return CustomDataClassGenerator.MakeSafeName (source, gen);
  163. }
  164. internal string TableColName (string source, ICodeGenerator gen)
  165. {
  166. if (CreateTableColumnName != null)
  167. return CreateTableColumnName (source, gen);
  168. else
  169. return CustomDataClassGenerator.MakeSafeName (source, gen);
  170. }
  171. internal string TableDelegateName (string source, ICodeGenerator gen)
  172. {
  173. if (CreateTableDelegateName != null)
  174. return CreateTableDelegateName (source, gen);
  175. else
  176. return CustomDataClassGenerator.MakeSafeName (source, gen) + "RowChangedEventHandler";
  177. }
  178. internal string EventArgsName (string source, ICodeGenerator gen)
  179. {
  180. if (CreateEventArgsName != null)
  181. return CreateEventArgsName (source, gen);
  182. else
  183. return CustomDataClassGenerator.MakeSafeName (source, gen) + "RowChangedEventArgs";
  184. }
  185. internal string ColumnName (string source, ICodeGenerator gen)
  186. {
  187. if (CreateColumnName != null)
  188. return CreateColumnName (source, gen);
  189. else
  190. return CustomDataClassGenerator.MakeSafeName (source, gen);
  191. }
  192. internal string RowName (string source, ICodeGenerator gen)
  193. {
  194. if (CreateRowName != null)
  195. return CreateRowName (source, gen);
  196. else
  197. return CustomDataClassGenerator.MakeSafeName (source, gen) + "Row";
  198. }
  199. internal string RelationName (string source, ICodeGenerator gen)
  200. {
  201. if (CreateRelationName != null)
  202. return CreateRelationName (source, gen);
  203. else
  204. return CustomDataClassGenerator.MakeSafeName (source, gen) + "Relation";
  205. }
  206. }
  207. internal class Generator
  208. {
  209. static ClassGeneratorOptions DefaultOptions = new ClassGeneratorOptions ();
  210. DataSet ds;
  211. CodeNamespace cns;
  212. ClassGeneratorOptions opts;
  213. ICodeGenerator gen;
  214. CodeTypeDeclaration dsType;
  215. public Generator (DataSet ds, CodeNamespace cns, ICodeGenerator gen, ClassGeneratorOptions options)
  216. {
  217. this.ds = ds;
  218. this.cns = cns;
  219. this.gen = gen;
  220. this.opts = opts;
  221. if (opts == null)
  222. opts = DefaultOptions;
  223. }
  224. public void Run ()
  225. {
  226. // using decls
  227. cns.Imports.Add (new CodeNamespaceImport ("System"));
  228. cns.Imports.Add (new CodeNamespaceImport ("System.Collections"));
  229. cns.Imports.Add (new CodeNamespaceImport ("System.ComponentModel"));
  230. cns.Imports.Add (new CodeNamespaceImport ("System.Data"));
  231. cns.Imports.Add (new CodeNamespaceImport ("System.Runtime.Serialization"));
  232. cns.Imports.Add (new CodeNamespaceImport ("System.Xml"));
  233. CodeTypeDeclaration dsType = GenerateDataSetType ();
  234. cns.Types.Add (dsType);
  235. foreach (DataTable dt in ds.Tables) {
  236. // 1. table types ([foo]DataTable)
  237. // 2. row types ([foo]Row)
  238. // 3. delegates ([foo]RowChangedEventHandler)
  239. // 4. eventargs ([foo]RowChangeEventArgs)
  240. CodeTypeDeclaration dtType = GenerateDataTableType (dt);
  241. CodeTypeDeclaration dtRow = GenerateDataRowType (dt);
  242. CodeTypeDelegate dtDelegate = new CodeTypeDelegate (opts.TableDelegateName (dt.TableName, gen));
  243. dtDelegate.Parameters.Add (Param (typeof (object), "o"));
  244. dtDelegate.Parameters.Add (Param (opts.EventArgsName (dt.TableName, gen), "e"));
  245. CodeTypeDeclaration dtEventType = GenerateEventType (dt);
  246. // Add types to either DataSet or CodeNamespace
  247. if (opts.MakeClassesInsideDataSet) {
  248. dsType.Members.Add (dtType);
  249. dsType.Members.Add (dtRow);
  250. dsType.Members.Add (dtDelegate);
  251. dsType.Members.Add (dtEventType);
  252. }
  253. else {
  254. cns.Types.Add (dtType);
  255. cns.Types.Add (dtRow);
  256. cns.Types.Add (dtDelegate);
  257. cns.Types.Add (dtEventType);
  258. }
  259. }
  260. }
  261. private CodeThisReferenceExpression This ()
  262. {
  263. return new CodeThisReferenceExpression ();
  264. }
  265. private CodeBaseReferenceExpression Base ()
  266. {
  267. return new CodeBaseReferenceExpression ();
  268. }
  269. private CodePrimitiveExpression Const (object value)
  270. {
  271. return new CodePrimitiveExpression (value);
  272. }
  273. private CodeTypeReference TypeRef (Type t)
  274. {
  275. return new CodeTypeReference (t);
  276. }
  277. private CodeTypeReference TypeRef (string name)
  278. {
  279. return new CodeTypeReference (name);
  280. }
  281. private CodeParameterDeclarationExpression Param (string t, string name)
  282. {
  283. return new CodeParameterDeclarationExpression (t, name);
  284. }
  285. private CodeParameterDeclarationExpression Param (Type t, string name)
  286. {
  287. return new CodeParameterDeclarationExpression (t, name);
  288. }
  289. private CodeParameterDeclarationExpression Param (CodeTypeReference t, string name)
  290. {
  291. return new CodeParameterDeclarationExpression (t, name);
  292. }
  293. private CodeArgumentReferenceExpression ParamRef (string name)
  294. {
  295. return new CodeArgumentReferenceExpression (name);
  296. }
  297. private CodeCastExpression Cast (string t, CodeExpression exp)
  298. {
  299. return new CodeCastExpression (t, exp);
  300. }
  301. private CodeCastExpression Cast (Type t, CodeExpression exp)
  302. {
  303. return new CodeCastExpression (t, exp);
  304. }
  305. private CodeCastExpression Cast (CodeTypeReference t, CodeExpression exp)
  306. {
  307. return new CodeCastExpression (t, exp);
  308. }
  309. private CodeExpression New (Type t, params CodeExpression [] parameters)
  310. {
  311. return new CodeObjectCreateExpression (t, parameters);
  312. }
  313. private CodeExpression New (string t, params CodeExpression [] parameters)
  314. {
  315. return new CodeObjectCreateExpression (TypeRef (t), parameters);
  316. }
  317. private CodeExpression NewArray (Type t, params CodeExpression [] parameters)
  318. {
  319. return new CodeArrayCreateExpression (t, parameters);
  320. }
  321. private CodeVariableReferenceExpression Local (string name)
  322. {
  323. return new CodeVariableReferenceExpression (name);
  324. }
  325. private CodeFieldReferenceExpression FieldRef (string name)
  326. {
  327. return new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), name);
  328. }
  329. private CodeFieldReferenceExpression FieldRef (CodeExpression exp, string name)
  330. {
  331. return new CodeFieldReferenceExpression (exp, name);
  332. }
  333. private CodePropertyReferenceExpression PropRef (string name)
  334. {
  335. return new CodePropertyReferenceExpression (new CodeThisReferenceExpression (), name);
  336. }
  337. private CodePropertyReferenceExpression PropRef (CodeExpression target, string name)
  338. {
  339. return new CodePropertyReferenceExpression (target, name);
  340. }
  341. private CodeIndexerExpression IndexerRef (CodeExpression target, CodeExpression parameters)
  342. {
  343. return new CodeIndexerExpression (target, parameters);
  344. }
  345. private CodeIndexerExpression IndexerRef (CodeExpression param)
  346. {
  347. return new CodeIndexerExpression (new CodeThisReferenceExpression (), param);
  348. }
  349. private CodeEventReferenceExpression EventRef (string name)
  350. {
  351. return new CodeEventReferenceExpression (new CodeThisReferenceExpression (), name);
  352. }
  353. private CodeEventReferenceExpression EventRef (CodeExpression target, string name)
  354. {
  355. return new CodeEventReferenceExpression (target, name);
  356. }
  357. private CodeMethodInvokeExpression MethodInvoke (string name, params CodeExpression [] parameters)
  358. {
  359. return new CodeMethodInvokeExpression (new CodeThisReferenceExpression (), name, parameters);
  360. }
  361. private CodeMethodInvokeExpression MethodInvoke (CodeExpression target, string name, params CodeExpression [] parameters)
  362. {
  363. return new CodeMethodInvokeExpression (target, name, parameters);
  364. }
  365. // note that this is "Identity" equality comparison
  366. private CodeBinaryOperatorExpression Equals (CodeExpression exp1, CodeExpression exp2)
  367. {
  368. return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.IdentityEquality, exp2);
  369. }
  370. private CodeBinaryOperatorExpression Inequals (CodeExpression exp1, CodeExpression exp2)
  371. {
  372. return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.IdentityInequality, exp2);
  373. }
  374. private CodeTypeReferenceExpression TypeRefExp (Type t)
  375. {
  376. return new CodeTypeReferenceExpression (t);
  377. }
  378. private CodeExpressionStatement Eval (CodeExpression exp)
  379. {
  380. return new CodeExpressionStatement (exp);
  381. }
  382. private CodeAssignStatement Let (CodeExpression exp, CodeExpression value)
  383. {
  384. return new CodeAssignStatement (exp, value);
  385. }
  386. private CodeMethodReturnStatement Return (CodeExpression exp)
  387. {
  388. return new CodeMethodReturnStatement (exp);
  389. }
  390. private CodeVariableDeclarationStatement VarDecl (Type t,
  391. string name, CodeExpression init)
  392. {
  393. return new CodeVariableDeclarationStatement (t, name, init);
  394. }
  395. private CodeVariableDeclarationStatement VarDecl (string t,
  396. string name, CodeExpression init)
  397. {
  398. return new CodeVariableDeclarationStatement (t, name, init);
  399. }
  400. private CodeCommentStatement Comment (string comment)
  401. {
  402. return new CodeCommentStatement (comment);
  403. }
  404. private CodeThrowExceptionStatement Throw (CodeExpression exp)
  405. {
  406. return new CodeThrowExceptionStatement (exp);
  407. }
  408. #region DataSet class
  409. private CodeTypeDeclaration GenerateDataSetType ()
  410. {
  411. // Type
  412. dsType = new CodeTypeDeclaration (opts.DataSetName (ds.DataSetName, gen));
  413. dsType.BaseTypes.Add (TypeRef (typeof (DataSet)));
  414. // .ctor()
  415. dsType.Members.Add (CreateDataSetDefaultCtor ());
  416. // runtime serialization .ctor()
  417. dsType.Members.Add (CreateDataSetSerializationCtor ());
  418. // Clone()
  419. dsType.Members.Add (CreateDataSetCloneMethod (dsType));
  420. // FIXME: I keep these methods out of the generated source right now.
  421. // It should be added after runtime serialization was implemented.
  422. /*
  423. // ShouldSerializeTables()
  424. dsType.Members.Add (CreateDataSetShouldSerializeTables ());
  425. // ShouldSerializeRelations()
  426. dsType.Members.Add (CreateDataSetShouldSerializeRelations ());
  427. // ReadXmlSerializable()
  428. dsType.Members.Add (CreateDataSetReadXmlSerializable ());
  429. // GetSchemaSerializable()
  430. dsType.Members.Add (CreateDataSetGetSchemaSerializable ());
  431. */
  432. dsType.Members.Add (CreateDataSetInitializeClass ());
  433. dsType.Members.Add (CreateDataSetInitializeFields ());
  434. dsType.Members.Add (CreateDataSetSchemaChanged ());
  435. // table class and members
  436. foreach (DataTable table in ds.Tables)
  437. CreateDataSetTableMembers (dsType, table);
  438. // relation class and members
  439. foreach (DataRelation rel in ds.Relations)
  440. CreateDataSetRelationMembers (dsType, rel);
  441. return dsType;
  442. }
  443. // Code:
  444. // public Foo ()
  445. // {
  446. // InitializeClass();
  447. // CollectionChangeEventHandler handler = new CollectionChangeEventHandler (SchemaChanged);
  448. // Tables.CollectionChanged += handler;
  449. // Relations.CollectionChanged += handler;
  450. // }
  451. private CodeConstructor CreateDataSetDefaultCtor ()
  452. {
  453. CodeConstructor ctor = new CodeConstructor ();
  454. ctor.Attributes = MemberAttributes.Public;
  455. // Code: InitializeClass().
  456. ctor.Statements.Add (Eval (MethodInvoke ("InitializeClass")));
  457. // Code: CollectionChangedEventHandler handler = new CollectionChangeEventHandler (SchemeChanged);
  458. CodeVariableDeclarationStatement stmt2 =
  459. VarDecl (
  460. typeof (CollectionChangeEventHandler),
  461. "handler",
  462. New (typeof (CollectionChangeEventHandler), FieldRef ("SchemaChanged")));
  463. ctor.Statements.Add (stmt2);
  464. // Code: Tables.CollectionChanged += handler;
  465. ctor.Statements.Add (
  466. new CodeAttachEventStatement (
  467. EventRef (
  468. PropRef ("Tables"),
  469. "CollectionChanged"),
  470. Local ("handler")));
  471. // Code: Relations.CollectionChanged += handler;
  472. ctor.Statements.Add (
  473. new CodeAttachEventStatement (
  474. EventRef (
  475. PropRef ("Relations"),
  476. "CollectionChanged"),
  477. Local ("handler")));
  478. return ctor;
  479. }
  480. // TODO: implement
  481. // Code:
  482. // protected Foo (SerializationInfo info, StreamingContext ctx)
  483. // {
  484. // throw new NotImplementedException ();
  485. // }
  486. private CodeConstructor CreateDataSetSerializationCtor ()
  487. {
  488. CodeConstructor ctor = new CodeConstructor ();
  489. ctor.Attributes = MemberAttributes.Family;
  490. ctor.Parameters.Add (Param (typeof (SerializationInfo), "info"));
  491. ctor.Parameters.Add (Param (typeof (StreamingContext), "ctx"));
  492. // Code:
  493. // // TODO: implement
  494. // throw new NotImplementedException ();
  495. ctor.Statements.Add (Comment ("TODO: implement"));
  496. ctor.Statements.Add (Throw (New (typeof (NotImplementedException))));
  497. return ctor;
  498. }
  499. // Code:
  500. // public override DataSet Clone()
  501. // {
  502. // [foo] set = ([foo]) base.Clone ();
  503. // set.InitializeFields ();
  504. // return set;
  505. // }
  506. private CodeMemberMethod CreateDataSetCloneMethod (CodeTypeDeclaration dsType)
  507. {
  508. CodeMemberMethod m = new CodeMemberMethod ();
  509. m.ReturnType = TypeRef (typeof (DataSet));
  510. m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
  511. m.Name = "Clone";
  512. // Code: [foo] set = ([foo]) base.Clone ();
  513. CodeVariableReferenceExpression set = Local ("set");
  514. m.Statements.Add (VarDecl (
  515. dsType.Name,
  516. "set",
  517. Cast (
  518. dsType.Name,
  519. MethodInvoke (Base (), "Clone"))));
  520. m.Statements.Add (Eval (MethodInvoke (set, "InitializeFields")));
  521. m.Statements.Add (Return (set));
  522. return m;
  523. }
  524. // Code:
  525. // protected override bool ShouldSerializeTables ()
  526. // {
  527. // return true; // it should be false
  528. // }
  529. private CodeMemberMethod CreateDataSetShouldSerializeTables ()
  530. {
  531. CodeMemberMethod m = new CodeMemberMethod ();
  532. m.Name = "ShouldSerializeTables";
  533. m.ReturnType = TypeRef (typeof (bool));
  534. m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
  535. // FIXME: set "false" after serialization .ctor() implementation
  536. m.Statements.Add (Return (Const (true)));
  537. return m;
  538. }
  539. // Code:
  540. // protected override bool ShouldSerializeRelations ()
  541. // {
  542. // return true; // it should be false
  543. // }
  544. private CodeMemberMethod CreateDataSetShouldSerializeRelations ()
  545. {
  546. CodeMemberMethod m = new CodeMemberMethod ();
  547. m.Name = "ShouldSerializeRelations";
  548. m.ReturnType = TypeRef (typeof (bool));
  549. m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
  550. // FIXME: set "false" after serialization .ctor() implementation
  551. m.Statements.Add (Return (Const (true)));
  552. return m;
  553. }
  554. // Code:
  555. // protected override void ReadXmlSerializable()
  556. // {
  557. // // TODO: implement
  558. // throw new NotImplementedException ();
  559. // }
  560. private CodeMemberMethod CreateDataSetReadXmlSerializable ()
  561. {
  562. CodeMemberMethod method = new CodeMemberMethod ();
  563. method.Name = "ReadXmlSerializable";
  564. method.Attributes = MemberAttributes.Family | MemberAttributes.Override;
  565. method.Parameters.Add (Param (TypeRef (typeof (XmlReader)), "reader"));
  566. // TODO: implemnet
  567. method.Statements.Add (Comment ("TODO: implement"));
  568. // Hey, how can I specify the constructor to invoke chained ctor with an empty parameter list!?
  569. method.Statements.Add (Throw (New (typeof (NotImplementedException))));
  570. return method;
  571. }
  572. private CodeMemberMethod CreateDataSetInitializeClass ()
  573. {
  574. CodeMemberMethod m = new CodeMemberMethod ();
  575. m.Name = "InitializeClass";
  576. m.Attributes = MemberAttributes.Assembly;
  577. // dataset properties
  578. m.Statements.Add (Let (PropRef ("DataSetName"), Const (ds.DataSetName)));
  579. m.Statements.Add (Let (PropRef ("Prefix"), Const (ds.Prefix)));
  580. m.Statements.Add (Let (PropRef ("Namespace"), Const (ds.Namespace)));
  581. m.Statements.Add (Let (PropRef ("Locale"), New (typeof (CultureInfo), Const (ds.Locale.Name))));
  582. m.Statements.Add (Let (PropRef ("CaseSensitive"), Const (ds.CaseSensitive)));
  583. m.Statements.Add (Let (PropRef ("EnforceConstraints"), Const (ds.EnforceConstraints)));
  584. // table
  585. foreach (DataTable dt in ds.Tables) {
  586. string tableFieldName = "__table" + opts.TableMemberName (dt.TableName, gen);
  587. string tableTypeName = opts.TableTypeName (dt.TableName, gen);
  588. m.Statements.Add (Let (FieldRef (tableFieldName), New (tableTypeName)));
  589. m.Statements.Add (Eval (MethodInvoke (PropRef ("Tables"), "Add", FieldRef (tableFieldName))));
  590. }
  591. bool fkcExists = false;
  592. bool ucExists = false;
  593. foreach (DataTable dt in ds.Tables) {
  594. string tname = "__table" + opts.TableMemberName (dt.TableName, gen);
  595. foreach (Constraint c in dt.Constraints) {
  596. UniqueConstraint uc = c as UniqueConstraint;
  597. if (uc != null) {
  598. if (!ucExists) {
  599. m.Statements.Add (VarDecl (typeof (UniqueConstraint), "uc", null));
  600. ucExists = true;
  601. }
  602. CreateUniqueKeyStatements (m, uc, tname);
  603. continue;
  604. }
  605. ForeignKeyConstraint fkc = c as ForeignKeyConstraint;
  606. if (fkc != null) {
  607. if (!fkcExists) {
  608. m.Statements.Add (VarDecl (typeof (ForeignKeyConstraint), "fkc", null));
  609. fkcExists = true;
  610. }
  611. CreateForeignKeyStatements (m, fkc, tname);
  612. }
  613. // What if other cases? dunno. Just ignore ;-)
  614. }
  615. }
  616. foreach (DataRelation rel in ds.Relations) {
  617. string relName = opts.RelationName (rel.RelationName, gen);
  618. ArrayList pcols = new ArrayList ();
  619. foreach (DataColumn pcol in rel.ParentColumns)
  620. pcols.Add (IndexerRef (PropRef (FieldRef ("__table" + opts.TableMemberName (rel.ParentTable.TableName, gen)), "Columns"), Const (pcol.ColumnName)));
  621. ArrayList ccols = new ArrayList ();
  622. foreach (DataColumn ccol in rel.ChildColumns)
  623. ccols.Add (IndexerRef (PropRef (FieldRef ("__table" + opts.TableMemberName (rel.ChildTable.TableName, gen)), "Columns"), Const (ccol.ColumnName)));
  624. // relation field
  625. string fieldName = "__relation" + relName;
  626. m.Statements.Add (Let (FieldRef (fieldName), New (typeof (DataRelation),
  627. Const (rel.RelationName),
  628. NewArray (typeof (DataColumn), pcols.ToArray (typeof (CodeExpression)) as CodeExpression []),
  629. NewArray (typeof (DataColumn), ccols.ToArray (typeof (CodeExpression)) as CodeExpression []),
  630. Const (false)
  631. )));
  632. m.Statements.Add (Let (PropRef (FieldRef (fieldName), "Nested"), Const (rel.Nested)));
  633. }
  634. return m;
  635. }
  636. private void CreateUniqueKeyStatements (CodeMemberMethod m, UniqueConstraint uc, string tableField)
  637. {
  638. ArrayList al = new ArrayList ();
  639. foreach (DataColumn col in uc.Columns)
  640. al.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
  641. m.Statements.Add (Let (Local ("uc"), New (
  642. typeof (UniqueConstraint),
  643. Const (uc.ConstraintName),
  644. NewArray (
  645. typeof (DataColumn),
  646. al.ToArray (typeof (CodeExpression)) as CodeExpression []),
  647. Const (uc.IsPrimaryKey))));
  648. m.Statements.Add (MethodInvoke (PropRef (FieldRef (tableField), "Constraints"), "Add", Local ("uc")));
  649. }
  650. private void CreateForeignKeyStatements (CodeMemberMethod m,ForeignKeyConstraint fkc, string tableField)
  651. {
  652. ArrayList pcols = new ArrayList ();
  653. foreach (DataColumn col in fkc.Columns)
  654. pcols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
  655. ArrayList ccols = new ArrayList ();
  656. foreach (DataColumn col in fkc.RelatedColumns)
  657. pcols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
  658. m.Statements.Add (Let (Local ("fkc"), New (
  659. typeof (ForeignKeyConstraint),
  660. Const (fkc.ConstraintName),
  661. NewArray (
  662. typeof (DataColumn),
  663. pcols.ToArray (typeof (CodeExpression)) as CodeExpression []),
  664. NewArray (
  665. typeof (DataColumn),
  666. ccols.ToArray (typeof (CodeExpression)) as CodeExpression []))));
  667. m.Statements.Add (Let (
  668. PropRef (Local ("fkc"), "AcceptRejectRule"),
  669. FieldRef (TypeRefExp (typeof (AcceptRejectRule)), Enum.GetName (typeof (AcceptRejectRule), fkc.AcceptRejectRule))));
  670. m.Statements.Add (Let (
  671. PropRef (Local ("fkc"), "DeleteRule"),
  672. FieldRef (TypeRefExp (typeof (Rule)), Enum.GetName (typeof (Rule), fkc.DeleteRule))));
  673. m.Statements.Add (Let (
  674. PropRef (Local ("fkc"), "UpdateRule"),
  675. FieldRef (TypeRefExp (typeof (Rule)), Enum.GetName (typeof (Rule), fkc.UpdateRule))));
  676. m.Statements.Add (MethodInvoke (PropRef (FieldRef (tableField), "Constraints"), "Add", Local ("fkc")));
  677. }
  678. private CodeMemberMethod CreateDataSetInitializeFields ()
  679. {
  680. CodeMemberMethod m = new CodeMemberMethod ();
  681. m.Attributes = MemberAttributes.Assembly;
  682. m.Name = "InitializeFields";
  683. foreach (DataTable dt in ds.Tables)
  684. m.Statements.Add (Eval (MethodInvoke (FieldRef ("__table" + opts.TableMemberName (dt.TableName, gen)), "InitializeFields")));
  685. foreach (DataRelation rel in ds.Relations)
  686. m.Statements.Add (Let (FieldRef ("__relation" + opts.RelationName (rel.RelationName, gen)), IndexerRef (PropRef ("Relations"), Const (rel.RelationName))));
  687. return m;
  688. }
  689. private CodeMemberMethod CreateDataSetSchemaChanged ()
  690. {
  691. CodeMemberMethod m = new CodeMemberMethod ();
  692. m.Name = "SchemaChanged";
  693. m.Parameters.Add (Param (typeof (object), "sender"));
  694. m.Parameters.Add (Param (typeof (CollectionChangeEventArgs), "e"));
  695. m.Statements.Add (
  696. new CodeConditionStatement (
  697. Equals (
  698. PropRef (ParamRef ("e"), "Action"),
  699. FieldRef (TypeRefExp (typeof (CollectionChangeAction)), "Remove")),
  700. new CodeStatement [] { Eval (MethodInvoke ("InitializeFields")) },
  701. new CodeStatement [] {}));
  702. return m;
  703. }
  704. private void CreateDataSetTableMembers (CodeTypeDeclaration dsType, DataTable table)
  705. {
  706. string tableTypeName = opts.TableTypeName (table.TableName, gen);
  707. string tableVarName = opts.TableMemberName (table.TableName, gen);
  708. CodeMemberField privTable = new CodeMemberField ();
  709. privTable.Type = TypeRef (tableTypeName);
  710. privTable.Name = "__table" + tableVarName;
  711. dsType.Members.Add (privTable);
  712. CodeMemberProperty pubTable = new CodeMemberProperty ();
  713. pubTable.Type = TypeRef (tableTypeName);
  714. pubTable.Attributes = MemberAttributes.Public;
  715. pubTable.Name = tableVarName;
  716. pubTable.HasSet = false;
  717. // Code: return __table[foo];
  718. pubTable.GetStatements.Add (Return (FieldRef ("__table" + tableVarName)));
  719. dsType.Members.Add (pubTable);
  720. }
  721. private void CreateDataSetRelationMembers (CodeTypeDeclaration dsType, DataRelation relation)
  722. {
  723. string relName = opts.RelationName (relation.RelationName, gen);
  724. string fieldName = "__relation" + relName;
  725. CodeMemberField field = new CodeMemberField ();
  726. field.Type = TypeRef (typeof (DataRelation));
  727. field.Name = fieldName;
  728. dsType.Members.Add (field);
  729. // This is not supported in MS.NET
  730. CodeMemberProperty prop = new CodeMemberProperty ();
  731. prop.Type = TypeRef (typeof (DataRelation));
  732. prop.Attributes = MemberAttributes.Public;
  733. prop.Name = relName;
  734. prop.HasSet = false;
  735. // Code: return __relation[foo_bar];
  736. prop.GetStatements.Add (Return (FieldRef (fieldName)));
  737. dsType.Members.Add (prop);
  738. }
  739. #endregion
  740. #region DataTable class
  741. private CodeTypeDeclaration GenerateDataTableType (DataTable dt)
  742. {
  743. CodeTypeDeclaration t = new CodeTypeDeclaration ();
  744. t.Name = opts.TableTypeName (dt.TableName, gen);
  745. t.BaseTypes.Add (TypeRef (typeof (DataTable)));
  746. t.BaseTypes.Add (TypeRef (typeof (IEnumerable)));
  747. t.Members.Add (CreateTableCtor1 (dt));
  748. t.Members.Add (CreateTableCtor2 (dt));
  749. t.Members.Add (CreateTableCount (dt));
  750. t.Members.Add (CreateTableIndexer (dt));
  751. t.Members.Add (CreateTableInitializeClass (dt));
  752. t.Members.Add (CreateTableInitializeFields (dt));
  753. t.Members.Add (CreateTableGetEnumerator (dt));
  754. t.Members.Add (CreateTableClone (dt));
  755. t.Members.Add (CreateTableCreateInstance (dt));
  756. t.Members.Add (CreateTableAddRow1 (dt));
  757. t.Members.Add (CreateTableAddRow2 (dt));
  758. t.Members.Add (CreateTableNewRow (dt));
  759. t.Members.Add (CreateTableNewRowFromBuilder (dt));
  760. t.Members.Add (CreateTableRemoveRow (dt));
  761. t.Members.Add (CreateTableGetRowType (dt));
  762. t.Members.Add (CreateTableEventStarter (dt, "Changing"));
  763. t.Members.Add (CreateTableEventStarter (dt, "Changed"));
  764. t.Members.Add (CreateTableEventStarter (dt, "Deleting"));
  765. t.Members.Add (CreateTableEventStarter (dt, "Deleted"));
  766. // events
  767. t.Members.Add (CreateTableEvent (dt, "RowChanging"));
  768. t.Members.Add (CreateTableEvent (dt, "RowChanged"));
  769. t.Members.Add (CreateTableEvent (dt, "RowDeleting"));
  770. t.Members.Add (CreateTableEvent (dt, "RowDeleted"));
  771. // column members
  772. foreach (DataColumn col in dt.Columns) {
  773. t.Members.Add (CreateTableColumnField (dt, col));
  774. t.Members.Add (CreateTableColumnProperty (dt, col));
  775. }
  776. return t;
  777. }
  778. // Code:
  779. // internal [foo]DataTable () : base ("[foo]")
  780. // {
  781. // InitializeClass ();
  782. // }
  783. private CodeConstructor CreateTableCtor1 (DataTable dt)
  784. {
  785. CodeConstructor c = new CodeConstructor ();
  786. c.Attributes = MemberAttributes.Assembly;
  787. c.BaseConstructorArgs.Add (Const (dt.TableName));
  788. c.Statements.Add (Eval (MethodInvoke ("InitializeClass")));
  789. return c;
  790. }
  791. // Code:
  792. // internal [foo]DataTable (DataTable table) : base (table.TableName)
  793. // {
  794. // // TODO: implement
  795. // throw new NotImplementedException ();
  796. // }
  797. private CodeConstructor CreateTableCtor2 (DataTable dt)
  798. {
  799. CodeConstructor c = new CodeConstructor ();
  800. c.Attributes = MemberAttributes.Assembly;
  801. c.Parameters.Add (Param (typeof (DataTable), "table"));
  802. c.BaseConstructorArgs.Add (PropRef (ParamRef ("table"), "TableName"));
  803. // TODO: implement
  804. c.Statements.Add (Comment ("TODO: implement"));
  805. c.Statements.Add (Throw (New (typeof (NotImplementedException))));
  806. return c;
  807. }
  808. private CodeMemberMethod CreateTableInitializeClass (DataTable dt)
  809. {
  810. CodeMemberMethod m = new CodeMemberMethod ();
  811. m.Name = "InitializeClass";
  812. foreach (DataColumn col in dt.Columns) {
  813. m.Statements.Add (Eval (MethodInvoke (
  814. PropRef ("Columns"),
  815. "Add",
  816. New (typeof (DataColumn), Const (col.ColumnName)))));
  817. }
  818. return m;
  819. }
  820. private CodeMemberMethod CreateTableInitializeFields (DataTable dt)
  821. {
  822. CodeMemberMethod m = new CodeMemberMethod ();
  823. m.Name = "InitializeFields";
  824. m.Attributes = MemberAttributes.Assembly;
  825. foreach (DataColumn col in dt.Columns)
  826. m.Statements.Add (Let (FieldRef ("__column" + opts.TableColName (col.ColumnName, gen)), IndexerRef (PropRef ("Columns"), Const (col.ColumnName))));
  827. return m;
  828. }
  829. private CodeMemberMethod CreateTableClone (DataTable dt)
  830. {
  831. CodeMemberMethod m = new CodeMemberMethod ();
  832. m.Name = "Clone";
  833. m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
  834. m.ReturnType = TypeRef (typeof (DataTable));
  835. string typeName = opts.TableTypeName (dt.TableName, gen);
  836. m.Statements.Add (
  837. VarDecl (typeName, "t", Cast (typeName, MethodInvoke (Base (), "Clone"))));
  838. m.Statements.Add (Eval (MethodInvoke (Local ("t"), "InitializeFields")));
  839. m.Statements.Add (Return (Local ("t")));
  840. return m;
  841. }
  842. private CodeMemberMethod CreateTableGetEnumerator (DataTable dt)
  843. {
  844. CodeMemberMethod m = new CodeMemberMethod ();
  845. m.Name = "GetEnumerator";
  846. m.Attributes = MemberAttributes.Public;
  847. m.ReturnType = TypeRef (typeof (IEnumerator));
  848. m.Statements.Add (Return (MethodInvoke (PropRef ("Rows"), "GetEnumerator")));
  849. return m;
  850. }
  851. private CodeMemberMethod CreateTableCreateInstance (DataTable dt)
  852. {
  853. CodeMemberMethod m = new CodeMemberMethod ();
  854. m.Name = "CreateInstance";
  855. m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
  856. m.ReturnType = TypeRef (typeof (DataTable));
  857. m.Statements.Add (Return (New (opts.TableTypeName (dt.TableName, gen))));
  858. return m;
  859. }
  860. private CodeMemberField CreateTableColumnField (DataTable dt, DataColumn col)
  861. {
  862. CodeMemberField f = new CodeMemberField ();
  863. f.Name = "__column" + opts.ColumnName (col.ColumnName, gen);
  864. f.Type = TypeRef (typeof (DataColumn));
  865. return f;
  866. }
  867. private CodeMemberProperty CreateTableColumnProperty (DataTable dt, DataColumn col)
  868. {
  869. string name = opts.ColumnName (col.ColumnName, gen);
  870. CodeMemberProperty p = new CodeMemberProperty ();
  871. p.Name = name + "Column";
  872. p.Attributes = MemberAttributes.Assembly;
  873. p.Type = TypeRef (typeof (DataColumn));
  874. p.HasSet = false;
  875. p.GetStatements.Add (Return (FieldRef ("__column" + name)));
  876. return p;
  877. }
  878. private CodeMemberProperty CreateTableCount (DataTable dt)
  879. {
  880. CodeMemberProperty p = new CodeMemberProperty ();
  881. p.Name = "Count";
  882. p.Attributes = MemberAttributes.Public;
  883. p.Type = TypeRef (typeof (int));
  884. p.HasSet = false;
  885. p.GetStatements.Add (Return (PropRef (PropRef ("Rows"), "Count")));
  886. return p;
  887. }
  888. private CodeMemberProperty CreateTableIndexer (DataTable dt)
  889. {
  890. string rowName = opts.RowName (dt.TableName, gen);
  891. CodeMemberProperty ix = new CodeMemberProperty ();
  892. ix.Name = "Item"; // indexer
  893. ix.Attributes = MemberAttributes.Public;
  894. ix.Type = TypeRef (rowName);
  895. ix.Parameters.Add (Param (typeof (int), "i"));
  896. ix.HasSet = false;
  897. ix.GetStatements.Add (Return (Cast (rowName, IndexerRef (PropRef ("Rows"), ParamRef ("i")))));
  898. return ix;
  899. }
  900. private CodeMemberMethod CreateTableAddRow1 (DataTable dt)
  901. {
  902. CodeMemberMethod m = new CodeMemberMethod ();
  903. string rowType = opts.RowName (dt.TableName, gen);
  904. m.Name = "Add" + rowType;
  905. m.Attributes = MemberAttributes.Public;
  906. m.Parameters.Add (Param (TypeRef (rowType), "row"));
  907. m.Statements.Add (Eval (MethodInvoke (PropRef ("Rows"), "Add", ParamRef ("row"))));
  908. return m;
  909. }
  910. private CodeMemberMethod CreateTableAddRow2 (DataTable dt)
  911. {
  912. CodeMemberMethod m = new CodeMemberMethod ();
  913. string rowType = opts.RowName (dt.TableName, gen);
  914. m.Name = "Add" + rowType;
  915. m.ReturnType = TypeRef (rowType);
  916. m.Attributes = MemberAttributes.Public;
  917. m.Statements.Add (VarDecl (rowType, "row", MethodInvoke ("New" + rowType)));
  918. foreach (DataColumn col in dt.Columns) {
  919. if (col.ColumnMapping == MappingType.Hidden) {
  920. foreach (DataRelation r in dt.DataSet.Relations) {
  921. if (r.ChildTable == dt) {
  922. // parameter
  923. string paramType = opts.RowName (r.ParentTable.TableName, gen);
  924. string paramName = paramType;
  925. m.Parameters.Add (Param (paramType, paramName));
  926. // CODE: SetParentRow (fooRow, DataSet.Relations ["foo_bar"]);
  927. m.Statements.Add (Eval (MethodInvoke (Local ("row"), "SetParentRow", ParamRef (paramName), IndexerRef (PropRef (PropRef ("DataSet"), "Relations"), Const (r.RelationName)))));
  928. break;
  929. }
  930. }
  931. }
  932. else {
  933. // parameter
  934. string paramName = opts.ColumnName (col.ColumnName, gen);
  935. m.Parameters.Add (Param (col.DataType, paramName));
  936. // row ["foo"] = foo;
  937. m.Statements.Add (Let (IndexerRef (Local ("row"), Const (paramName)), ParamRef (paramName)));
  938. }
  939. }
  940. // Rows.Add (row);
  941. m.Statements.Add (MethodInvoke (PropRef ("Rows"), "Add", Local ("row")));
  942. m.Statements.Add (Return (Local ("row")));
  943. return m;
  944. }
  945. private CodeMemberMethod CreateTableNewRow (DataTable dt)
  946. {
  947. CodeMemberMethod m = new CodeMemberMethod ();
  948. string rowType = opts.RowName (dt.TableName, gen);
  949. m.Name = "New" + rowType;
  950. m.ReturnType = TypeRef (rowType);
  951. m.Attributes = MemberAttributes.Public;
  952. m.Statements.Add (Return (Cast (rowType, MethodInvoke ("NewRow"))));
  953. return m;
  954. }
  955. private CodeMemberMethod CreateTableNewRowFromBuilder (DataTable dt)
  956. {
  957. CodeMemberMethod m = new CodeMemberMethod ();
  958. m.Name = "NewRowFromBuilder";
  959. m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
  960. m.ReturnType = TypeRef (typeof (DataRow));
  961. m.Parameters.Add (Param (typeof (DataRowBuilder), "builder"));
  962. m.Statements.Add (Return (New (opts.RowName (dt.TableName, gen), ParamRef ("builder"))));
  963. return m;
  964. }
  965. private CodeMemberMethod CreateTableRemoveRow (DataTable dt)
  966. {
  967. CodeMemberMethod m = new CodeMemberMethod ();
  968. string rowType = opts.RowName (dt.TableName, gen);
  969. m.Name = "Remove" + rowType;
  970. m.Attributes = MemberAttributes.Public;
  971. m.Parameters.Add (Param (TypeRef (rowType), "row"));
  972. m.Statements.Add (Eval (MethodInvoke (PropRef ("Rows"), "Remove", ParamRef ("row"))));
  973. return m;
  974. }
  975. private CodeMemberMethod CreateTableGetRowType (DataTable dt)
  976. {
  977. CodeMemberMethod m = new CodeMemberMethod ();
  978. m.Name = "GetRowType";
  979. m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
  980. m.ReturnType = TypeRef (typeof (Type));
  981. m.Statements.Add (Return (new CodeTypeOfExpression (opts.RowName (dt.TableName, gen))));
  982. return m;
  983. }
  984. private CodeMemberMethod CreateTableEventStarter (DataTable dt, string type)
  985. {
  986. CodeMemberMethod m = new CodeMemberMethod ();
  987. m.Name = "OnRow" + type;
  988. m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
  989. m.Parameters.Add (Param (typeof (DataRowChangeEventArgs), "e"));
  990. m.Statements.Add (Eval (MethodInvoke (
  991. Base (),
  992. m.Name,
  993. ParamRef ("e"))));
  994. string eventName = opts.TableMemberName (dt.TableName, gen) + "Row" + type;
  995. CodeStatement trueStmt = Eval (
  996. MethodInvoke (
  997. eventName,
  998. This (),
  999. New (
  1000. opts.EventArgsName (dt.TableName, gen),
  1001. Cast (opts.RowName (dt.TableName, gen), PropRef (ParamRef ("e"), "Row")),
  1002. PropRef (ParamRef ("e"), "Action"))));
  1003. m.Statements.Add (
  1004. new CodeConditionStatement (
  1005. Inequals (EventRef (eventName), Const (null)),
  1006. new CodeStatement [] {trueStmt},
  1007. new CodeStatement [] {}));
  1008. return m;
  1009. }
  1010. private CodeMemberEvent CreateTableEvent (DataTable dt, string nameSuffix)
  1011. {
  1012. CodeMemberEvent cme = new CodeMemberEvent ();
  1013. cme.Attributes = MemberAttributes.Public;
  1014. cme.Name = opts.TableMemberName (dt.TableName, gen) + nameSuffix;
  1015. cme.Type = TypeRef (opts.TableDelegateName (dt.TableName, gen));
  1016. return cme;
  1017. }
  1018. #endregion
  1019. #region Row class
  1020. public CodeTypeDeclaration GenerateDataRowType (DataTable dt)
  1021. {
  1022. CodeTypeDeclaration t = new CodeTypeDeclaration ();
  1023. t.Name = opts.RowName (dt.TableName, gen);
  1024. t.BaseTypes.Add (TypeRef (typeof (DataRow)));
  1025. t.Members.Add (CreateRowCtor (dt));
  1026. t.Members.Add (CreateRowTableField (dt));
  1027. foreach (DataColumn col in dt.Columns) {
  1028. if (col.ColumnMapping != MappingType.Hidden) {
  1029. t.Members.Add (CreateRowColumnProperty (dt, col));
  1030. t.Members.Add (CreateRowColumnIsNull (dt, col));
  1031. t.Members.Add (CreateRowColumnSetNull (dt, col));
  1032. }
  1033. }
  1034. foreach (DataRelation rel in dt.ParentRelations)
  1035. t.Members.Add (CreateRowParentRowProperty (dt, rel));
  1036. foreach (DataRelation rel in dt.ChildRelations)
  1037. t.Members.Add (CreateRowGetChildRows (dt, rel));
  1038. return t;
  1039. }
  1040. private CodeConstructor CreateRowCtor (DataTable dt)
  1041. {
  1042. CodeConstructor c = new CodeConstructor ();
  1043. c.Attributes = MemberAttributes.Assembly;
  1044. c.Parameters.Add (Param (typeof (DataRowBuilder), "builder"));
  1045. c.BaseConstructorArgs.Add (ParamRef ("builder"));
  1046. c.Statements.Add (Let (FieldRef ("table"), Cast (
  1047. opts.TableTypeName (dt.TableName, gen),
  1048. PropRef ("Table"))));
  1049. return c;
  1050. }
  1051. private CodeMemberField CreateRowTableField (DataTable dt)
  1052. {
  1053. CodeMemberField f = new CodeMemberField ();
  1054. f.Name = "table";
  1055. f.Type = TypeRef (opts.TableTypeName (dt.TableName, gen));
  1056. return f;
  1057. }
  1058. private CodeMemberProperty CreateRowColumnProperty (DataTable dt, DataColumn col)
  1059. {
  1060. CodeMemberProperty p = new CodeMemberProperty ();
  1061. p.Name = opts.ColumnName (col.ColumnName, gen);
  1062. p.Type = TypeRef (col.DataType);
  1063. p.Attributes = MemberAttributes.Public;
  1064. // This part should be better than MS code output.
  1065. // Code:
  1066. // object ret = this [col];
  1067. // if (ret == DBNull.Value)
  1068. // throw new StrongTypingException ()
  1069. // else
  1070. // return (type) ret;
  1071. p.GetStatements.Add (VarDecl (typeof (object), "ret",
  1072. IndexerRef (PropRef
  1073. (PropRef ("table"),
  1074. opts.TableColName (col.ColumnName, gen) + "Column"))));
  1075. p.GetStatements.Add (new CodeConditionStatement (
  1076. Equals (
  1077. Local ("ret"),
  1078. PropRef (TypeRefExp (typeof (DBNull)), "Value")),
  1079. new CodeStatement [] {
  1080. Throw (New (typeof (StrongTypingException), Const ("Cannot get strong typed value since it is DB null."), Const (null))) },
  1081. new CodeStatement [] {
  1082. Return (Cast (col.DataType, Local ("ret"))) }));
  1083. p.SetStatements.Add (Let (IndexerRef (PropRef (PropRef ("table"), opts.TableColName (col.ColumnName, gen) + "Column")), new CodePropertySetValueReferenceExpression ()));
  1084. return p;
  1085. }
  1086. private CodeMemberMethod CreateRowColumnIsNull (DataTable dt, DataColumn col)
  1087. {
  1088. CodeMemberMethod m = new CodeMemberMethod ();
  1089. m.Name = "Is" + opts.ColumnName (col.ColumnName, gen) + "Null";
  1090. m.Attributes = MemberAttributes.Public;
  1091. m.ReturnType = TypeRef (typeof (bool));
  1092. m.Statements.Add (Return (MethodInvoke (
  1093. "IsNull",
  1094. // table[foo].[bar]Column
  1095. PropRef (
  1096. PropRef ("table"),
  1097. opts.TableColName (col.ColumnName, gen) + "Column"))));
  1098. return m;
  1099. }
  1100. private CodeMemberMethod CreateRowColumnSetNull (DataTable dt, DataColumn col)
  1101. {
  1102. CodeMemberMethod m = new CodeMemberMethod ();
  1103. m.Name = "Set" + opts.ColumnName (col.ColumnName, gen) + "Null";
  1104. m.Attributes = MemberAttributes.Public;
  1105. m.Statements.Add (Let (IndexerRef (
  1106. PropRef (
  1107. PropRef ("table"),
  1108. opts.TableColName (col.ColumnName, gen) + "Column")),
  1109. PropRef (TypeRefExp (typeof (DBNull)), "Value")));
  1110. return m;
  1111. }
  1112. private CodeMemberProperty CreateRowParentRowProperty (DataTable dt, DataRelation rel)
  1113. {
  1114. CodeMemberProperty p = new CodeMemberProperty ();
  1115. p.Name = opts.TableMemberName (rel.ParentTable.TableName, gen) + "Row";
  1116. p.Attributes = MemberAttributes.Public;
  1117. p.Type = TypeRef (opts.RowName (rel.ParentTable.TableName, gen));
  1118. p.GetStatements.Add (Return (Cast (p.Type, MethodInvoke (
  1119. "GetParentRow",
  1120. IndexerRef (
  1121. PropRef (
  1122. PropRef (
  1123. PropRef ("Table"),
  1124. "DataSet"),
  1125. "Relations"),
  1126. Const (rel.RelationName))))));
  1127. p.SetStatements.Add (Eval (MethodInvoke (
  1128. "SetParentRow",
  1129. new CodePropertySetValueReferenceExpression (),
  1130. IndexerRef (
  1131. PropRef (
  1132. PropRef (
  1133. PropRef ("Table"),
  1134. "DataSet"),
  1135. "Relations"),
  1136. Const (rel.RelationName)))));
  1137. return p;
  1138. }
  1139. private CodeMemberMethod CreateRowGetChildRows (DataTable dt, DataRelation rel)
  1140. {
  1141. CodeMemberMethod m = new CodeMemberMethod ();
  1142. m.Name = "Get" + opts.TableMemberName (rel.ChildTable.TableName, gen) + "Rows";
  1143. m.Attributes = MemberAttributes.Public;
  1144. m.ReturnType = new CodeTypeReference (opts.RowName (rel.ChildTable.TableName, gen), 1);
  1145. m.Statements.Add (Return (Cast (m.ReturnType, MethodInvoke (
  1146. "GetChildRows",
  1147. IndexerRef (
  1148. PropRef (
  1149. PropRef (
  1150. PropRef ("Table"),
  1151. "DataSet"),
  1152. "Relations"),
  1153. Const (rel.RelationName))))));
  1154. return m;
  1155. }
  1156. #endregion
  1157. #region Event class
  1158. // Code:
  1159. // public class [foo]ChangeEventArgs : EventArgs
  1160. // {
  1161. // private [foo]Row row;
  1162. // private DataRowAction action;
  1163. // (.ctor())
  1164. // (Row)
  1165. // (Action)
  1166. // }
  1167. private CodeTypeDeclaration GenerateEventType (DataTable dt)
  1168. {
  1169. CodeTypeDeclaration t = new CodeTypeDeclaration ();
  1170. t.Name = opts.EventArgsName (dt.TableName, gen);
  1171. t.BaseTypes.Add (TypeRef (typeof (EventArgs)));
  1172. t.Attributes = MemberAttributes.Public;
  1173. t.Members.Add (
  1174. new CodeMemberField (
  1175. TypeRef (opts.RowName (dt.TableName, gen)),
  1176. "row"));
  1177. t.Members.Add (
  1178. new CodeMemberField (
  1179. TypeRef (typeof (DataRowAction)), "action"));
  1180. t.Members.Add (CreateEventCtor (dt));
  1181. t.Members.Add (CreateEventRow (dt));
  1182. t.Members.Add (CreateEventAction (dt));
  1183. return t;
  1184. }
  1185. // Code:
  1186. // public [foo]RowChangeEventArgs ([foo]Row r, DataRowAction a)
  1187. // {
  1188. // row = r;
  1189. // action = a;
  1190. // }
  1191. private CodeConstructor CreateEventCtor (DataTable dt)
  1192. {
  1193. CodeConstructor c = new CodeConstructor ();
  1194. c.Attributes = MemberAttributes.Public;
  1195. c.Parameters.Add (Param (TypeRef (opts.RowName (dt.TableName, gen)), "r"));
  1196. c.Parameters.Add (Param (TypeRef (typeof (DataRowAction)), "a"));
  1197. c.Statements.Add (Let (FieldRef ("row"), ParamRef ("r")));
  1198. c.Statements.Add (Let (FieldRef ("action"), ParamRef ("a")));
  1199. return c;
  1200. }
  1201. // Code:
  1202. // public [foo]Row Row {
  1203. // get { return row; }
  1204. // }
  1205. private CodeMemberProperty CreateEventRow (DataTable dt)
  1206. {
  1207. CodeMemberProperty p = new CodeMemberProperty ();
  1208. p.Name = "Row";
  1209. p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  1210. p.Type = TypeRef (opts.RowName (dt.TableName, gen));
  1211. p.HasSet = false;
  1212. p.GetStatements.Add (Return (FieldRef ("row")));
  1213. return p;
  1214. }
  1215. // Code:
  1216. // public DataRowAction Action {
  1217. // get { return action; }
  1218. // }
  1219. private CodeMemberProperty CreateEventAction (DataTable dt)
  1220. {
  1221. CodeMemberProperty p = new CodeMemberProperty ();
  1222. p.Name = "Action";
  1223. p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  1224. p.Type = TypeRef (typeof (DataRowAction));
  1225. p.HasSet = false;
  1226. p.GetStatements.Add (Return (FieldRef ("action")));
  1227. return p;
  1228. }
  1229. #endregion
  1230. }
  1231. }
  1232. /* =========================================================
  1233. MonoDataSetGenerator API notes
  1234. ** generator API:
  1235. CreateDataSetClasses (
  1236. DataSet ds,
  1237. CodeNamespace cns,
  1238. ICodeGenerator gen,
  1239. GeneratorOptions options)
  1240. ** classes:
  1241. *** Code naming method delegate
  1242. public delegate string CodeNamingMethod (string sourceName);
  1243. It is used in CodeGeneratorOptions (describled immediately below).
  1244. *** Generator Options
  1245. public bool MakeClassesInsideDataSet
  1246. indicates whether classes and delegates other than DataSet
  1247. itself are "contained" in the DataSet class or not.
  1248. public CodeNamingMethod CreateDataSetName;
  1249. public CodeNamingMethod CreateTableTypeName;
  1250. public CodeNamingMethod CreateTableMemberName;
  1251. public CodeNamingMethod CreateColumnName;
  1252. public CodeNamingMethod CreateRowName;
  1253. public CodeNamingMethod CreateRelationName;
  1254. public CodeNamingMethod CreateTableDelegateName;
  1255. public CodeNamingMethod CreateEventArgsName;
  1256. Custom methods each of that returns type or member name.
  1257. By default, they are set as to useTypedDataSetGenerator.
  1258. CreateIdName() with modifications listed as below:
  1259. DataSetName: as is
  1260. TableTypeName: "DataTable" suffix
  1261. TableMemberName: as is
  1262. ColumnName: as is
  1263. RowName: "Row" suffix
  1264. RelationName: (TBD; maybe had better have another delegate type)
  1265. DelegateName: "RowChangedEventHandler" suffix
  1266. EventArgsName: "RowChangedEventArgs" suffix
  1267. ** Auto Generated classes
  1268. 1. Custom DataSet class
  1269. class name = dataset name, encoded by options.CreateDataSetName().
  1270. *** .ctor
  1271. public default .ctor()
  1272. "initialize" class.
  1273. set custom delegate on Tables.CollectionChanged
  1274. set custom delegate on Relations.CollectionChanged
  1275. runtime serialization .ctor()
  1276. TBD
  1277. *** public members
  1278. data tables: [foo]DataTable foo { return this.table[foo]; }
  1279. Clone()
  1280. init variables on new dataset.
  1281. *** protected members
  1282. ShouldSerializeTables()
  1283. returns false, while default DataSet returns true.
  1284. ShouldSerializeRelations()
  1285. returns false, while default DataSet returns true.
  1286. ReadXmlSerializable() ... similar to runtime serialization
  1287. TBD
  1288. GetSchemaSerializable()
  1289. Write its schema to temporary MemoryStream
  1290. Read XML schema from the stream
  1291. *** internal members
  1292. "init variables"
  1293. set member fields (tables, relations)
  1294. call members' "init variables"
  1295. "init class"
  1296. set DataSetName, Prefix, Namespace, Locale, CaseSensitive, EnforceConstraints
  1297. for each table
  1298. allocate table[foo]
  1299. Tables.Add()
  1300. create FKC: new FKC([rel], new DataColumn [] {table[foo].[keyColumnName]Column}, new DataColumn [] {table[child].[childColName]Column}
  1301. fill Rule properties.
  1302. allocate relation[rel] and fill Nested, then Relations.Add()
  1303. *** private members
  1304. data tables: [foo]DataTable table[foo];
  1305. data relations: DataRelation relation[rel];
  1306. ShouldSerialize[foo]
  1307. 2. Custom DataTable classes for each DataTable
  1308. This class is created under the dataset.
  1309. *** internal members
  1310. .ctor() : base("[foo]")
  1311. initialize class
  1312. .ctor(DataTable)
  1313. wtf?
  1314. DataColumn [bar]Column { return column[bar]; }
  1315. "init variables"()
  1316. fill each column fields
  1317. *** public members
  1318. int Count { rowcount }
  1319. this [int index] { row [i]; }
  1320. event [foo]RowChangedEventHandler [foo]RowChanged
  1321. event [foo]RowChangedEventHandler [foo]RowChanging
  1322. event [foo]RowChangedEventHandler [foo]RowDeleted
  1323. event [foo]RowChangedEventHandler [foo]RowDeleting
  1324. void Add[foo]Row ([foo]Row row) { Rows.Add (row); }
  1325. [foo]Row Add[foo]Row ([columnType] [columnName])
  1326. create new [foo]row.
  1327. set members
  1328. Rows.Add ()
  1329. // where
  1330. // non-relation-children are just created as column type
  1331. // relation-children are typeof fooRow[]
  1332. GetEnumerator() { Rows.GetEnumerator (); }
  1333. override DataTable Clone()
  1334. "init variables"
  1335. [foo]Row New[foo]Row()
  1336. void Remove[foo]Row([foo]Row)
  1337. //for each ChildRelations
  1338. [bar]Row [] Get[foo_bar]Rows ()
  1339. *** protected members
  1340. override DataTable CreateInstance() { return new }
  1341. override DataRow NewRowFromBuilder(DataRowBuilder)
  1342. override Type GetRowType()
  1343. override void OnRowChanged(DataRowChangedEventArgs)
  1344. base.()
  1345. check this event [foo]RowChanged.
  1346. override void OnRowChanging(DataRowChangedEventArgs)
  1347. override void OnRowDeleted(DataRowChangedEventArgs)
  1348. override void OnRowDeleting(DataRowChangedEventArgs)
  1349. ... as well
  1350. *** private members
  1351. "initialize class"
  1352. for each columns {
  1353. column[bar] = new DataColumn (...);
  1354. Columns.Add()
  1355. }
  1356. DataColumn [bar]Column
  1357. 3. Custom DataRow classses
  1358. *** public members
  1359. for simple members:
  1360. [bar_type] [bar] {
  1361. get { try { } catch { throw StrongTypingException(); }
  1362. set { this [[foo]Table.[bar]Column] = value; }
  1363. bool Is[bar]Null ()
  1364. IsNull ([foo]Table.[bar]Column);
  1365. void Set[bar]Null ()
  1366. if the table is parent of some relations
  1367. public [child]Row [] Get[child]Rows()
  1368. *** internal members
  1369. .ctor(DataRowBuilder) : base.()
  1370. table[foo] = Table;
  1371. *** private members
  1372. [foo]DataTable table[foo]
  1373. 4. Custom DataRowChangeEvent classes
  1374. *** private members
  1375. [foo]Row eventRow
  1376. DataRowAction eventAction
  1377. *** public members
  1378. .ctor([foo]Row row, DataRowAction action)
  1379. [foo]Row Row
  1380. DataRowAction Action
  1381. 5. public Table RowChangedEventHandler delegates
  1382. [foo]RowChangedEventHandler(object, [foo]RowChangedEvent e)
  1383. ======================================================== */