**** Merged from MCS ****
[mono-project.git] / mcs / class / System.Data / System.Data / CustomDataClassGenerator.cs
blobefde5344b58c892f742b754832e6462e17278c74
1 //
2 // Mono.Data.CustomDataClassGenerator
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // (C)2004 Novell Inc.
8 //
9 // API notes are the bottom of the source.
11 // This class is standalone testable (even under MS.NET) when compiled with
12 // -d:DATACLASS_GENERATOR_STANDALONE .
16 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
18 // Permission is hereby granted, free of charge, to any person obtaining
19 // a copy of this software and associated documentation files (the
20 // "Software"), to deal in the Software without restriction, including
21 // without limitation the rights to use, copy, modify, merge, publish,
22 // distribute, sublicense, and/or sell copies of the Software, and to
23 // permit persons to whom the Software is furnished to do so, subject to
24 // the following conditions:
25 //
26 // The above copyright notice and this permission notice shall be
27 // included in all copies or substantial portions of the Software.
28 //
29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System;
38 using System.Xml;
39 using System.Data;
40 using System.Collections;
41 using System.CodeDom;
42 using System.Globalization;
43 using System.Text;
44 using System.CodeDom.Compiler;
45 using System.ComponentModel;
46 using System.Runtime.Serialization;
48 // only for Driver
49 using Microsoft.CSharp;
50 using System.IO;
52 namespace System.Data
55 #if DATACLASS_GENERATOR_STANDALONE
56 public class Driver
58 public static void Main (string [] args)
60 try {
61 if (args.Length < 1) {
62 Console.WriteLine ("mono dsgentest.exe filename");
63 return;
66 DataSet ds = new DataSet ();
67 ds.ReadXml (args [0]);
68 ICodeGenerator gen = new CSharpCodeProvider ().CreateGenerator ();
70 CodeNamespace cns = new CodeNamespace ("MyNamespace");
71 TextWriter tw = new StreamWriter (Path.ChangeExtension (args [0], ".ms.cs"), false, Encoding.Default);
72 TypedDataSetGenerator.Generate (ds, cns, gen);
73 gen.GenerateCodeFromNamespace (cns, tw, null);
74 tw.Close ();
76 cns = new CodeNamespace ("MyNamespace");
77 tw = new StreamWriter (Path.ChangeExtension (args [0], ".mono.cs"), false, Encoding.Default);
78 CustomDataClassGenerator.CreateDataSetClasses (ds, cns, gen, null);
79 gen.GenerateCodeFromNamespace (cns, tw, null);
80 tw.Close ();
81 } catch (Exception ex) {
82 Console.WriteLine (ex);
86 #endif
88 #if DATACLASS_GENERATOR_STANDALONE
89 public class CustomDataClassGenerator
90 #else
91 internal class CustomDataClassGenerator
92 #endif
94 public static void CreateDataSetClasses (DataSet ds,
95 CodeNamespace cns, ICodeGenerator gen,
96 ClassGeneratorOptions options)
98 new Generator (ds, cns, gen, options).Run ();
101 public static string MakeSafeName (string name, ICodeGenerator codeGen)
103 if (name == null || codeGen == null)
104 throw new NullReferenceException ();
106 name = codeGen.CreateValidIdentifier (name);
108 if (name.Length == 0)
109 return "_";
111 StringBuilder sb = null;
112 if (!Char.IsLetter (name, 0) && name [0] != '_') {
113 sb = new StringBuilder ();
114 sb.Append ('_');
117 int start = 0;
118 for (int i = 0; i < name.Length; i++) {
119 if (!Char.IsLetterOrDigit (name, i)) {
120 if (sb == null)
121 sb = new StringBuilder ();
122 sb.Append (name, start, i - start);
123 sb.Append ('_');
124 start = i + 1;
128 if (sb != null) {
129 sb.Append (name, start, name.Length - start);
130 return sb.ToString ();
132 else
133 return name;
137 #if DATACLASS_GENERATOR_STANDALONE
138 public delegate string CodeNamingMethod (string source, ICodeGenerator gen);
139 #else
140 internal delegate string CodeNamingMethod (string source, ICodeGenerator gen);
141 #endif
143 #if DATACLASS_GENERATOR_STANDALONE
144 public class ClassGeneratorOptions
145 #else
146 internal class ClassGeneratorOptions
147 #endif
149 public bool MakeClassesInsideDataSet = true; // default = MS compatible
151 public CodeNamingMethod CreateDataSetName;
152 public CodeNamingMethod CreateTableTypeName;
153 public CodeNamingMethod CreateTableMemberName;
154 public CodeNamingMethod CreateTableColumnName;
155 public CodeNamingMethod CreateColumnName;
156 public CodeNamingMethod CreateRowName;
157 public CodeNamingMethod CreateRelationName;
158 public CodeNamingMethod CreateTableDelegateName;
159 public CodeNamingMethod CreateEventArgsName;
161 internal string DataSetName (string source, ICodeGenerator gen)
163 if (CreateDataSetName != null)
164 return CreateDataSetName (source, gen);
165 else
166 return CustomDataClassGenerator.MakeSafeName (source, gen);
169 internal string TableTypeName (string source, ICodeGenerator gen)
171 if (CreateTableTypeName != null)
172 return CreateTableTypeName (source, gen);
173 else
174 return CustomDataClassGenerator.MakeSafeName (source, gen) + "DataTable";
177 internal string TableMemberName (string source, ICodeGenerator gen)
179 if (CreateTableMemberName != null)
180 return CreateTableMemberName (source, gen);
181 else
182 return CustomDataClassGenerator.MakeSafeName (source, gen);
185 internal string TableColName (string source, ICodeGenerator gen)
187 if (CreateTableColumnName != null)
188 return CreateTableColumnName (source, gen);
189 else
190 return CustomDataClassGenerator.MakeSafeName (source, gen);
193 internal string TableDelegateName (string source, ICodeGenerator gen)
195 if (CreateTableDelegateName != null)
196 return CreateTableDelegateName (source, gen);
197 else
198 return CustomDataClassGenerator.MakeSafeName (source, gen) + "RowChangedEventHandler";
201 internal string EventArgsName (string source, ICodeGenerator gen)
203 if (CreateEventArgsName != null)
204 return CreateEventArgsName (source, gen);
205 else
206 return CustomDataClassGenerator.MakeSafeName (source, gen) + "RowChangedEventArgs";
209 internal string ColumnName (string source, ICodeGenerator gen)
211 if (CreateColumnName != null)
212 return CreateColumnName (source, gen);
213 else
214 return CustomDataClassGenerator.MakeSafeName (source, gen);
217 internal string RowName (string source, ICodeGenerator gen)
219 if (CreateRowName != null)
220 return CreateRowName (source, gen);
221 else
222 return CustomDataClassGenerator.MakeSafeName (source, gen) + "Row";
225 internal string RelationName (string source, ICodeGenerator gen)
227 if (CreateRelationName != null)
228 return CreateRelationName (source, gen);
229 else
230 return CustomDataClassGenerator.MakeSafeName (source, gen) + "Relation";
234 internal class Generator
236 static ClassGeneratorOptions DefaultOptions = new ClassGeneratorOptions ();
238 DataSet ds;
239 CodeNamespace cns;
240 ClassGeneratorOptions opts;
241 ICodeGenerator gen;
243 CodeTypeDeclaration dsType;
245 public Generator (DataSet ds, CodeNamespace cns, ICodeGenerator gen, ClassGeneratorOptions options)
247 this.ds = ds;
248 this.cns = cns;
249 this.gen = gen;
250 this.opts = opts;
252 if (opts == null)
253 opts = DefaultOptions;
256 public void Run ()
258 // using decls
259 cns.Imports.Add (new CodeNamespaceImport ("System"));
260 cns.Imports.Add (new CodeNamespaceImport ("System.Collections"));
261 cns.Imports.Add (new CodeNamespaceImport ("System.ComponentModel"));
262 cns.Imports.Add (new CodeNamespaceImport ("System.Data"));
263 cns.Imports.Add (new CodeNamespaceImport ("System.Runtime.Serialization"));
264 cns.Imports.Add (new CodeNamespaceImport ("System.Xml"));
267 CodeTypeDeclaration dsType = GenerateDataSetType ();
268 cns.Types.Add (dsType);
269 foreach (DataTable dt in ds.Tables) {
270 // 1. table types ([foo]DataTable)
271 // 2. row types ([foo]Row)
272 // 3. delegates ([foo]RowChangedEventHandler)
273 // 4. eventargs ([foo]RowChangeEventArgs)
275 CodeTypeDeclaration dtType = GenerateDataTableType (dt);
277 CodeTypeDeclaration dtRow = GenerateDataRowType (dt);
279 CodeTypeDelegate dtDelegate = new CodeTypeDelegate (opts.TableDelegateName (dt.TableName, gen));
280 dtDelegate.Parameters.Add (Param (typeof (object), "o"));
281 dtDelegate.Parameters.Add (Param (opts.EventArgsName (dt.TableName, gen), "e"));
283 CodeTypeDeclaration dtEventType = GenerateEventType (dt);
285 // Add types to either DataSet or CodeNamespace
286 if (opts.MakeClassesInsideDataSet) {
287 dsType.Members.Add (dtType);
288 dsType.Members.Add (dtRow);
289 dsType.Members.Add (dtDelegate);
290 dsType.Members.Add (dtEventType);
292 else {
293 cns.Types.Add (dtType);
294 cns.Types.Add (dtRow);
295 cns.Types.Add (dtDelegate);
296 cns.Types.Add (dtEventType);
301 private CodeThisReferenceExpression This ()
303 return new CodeThisReferenceExpression ();
306 private CodeBaseReferenceExpression Base ()
308 return new CodeBaseReferenceExpression ();
311 private CodePrimitiveExpression Const (object value)
313 return new CodePrimitiveExpression (value);
316 private CodeTypeReference TypeRef (Type t)
318 return new CodeTypeReference (t);
321 private CodeTypeReference TypeRef (string name)
323 return new CodeTypeReference (name);
326 private CodeParameterDeclarationExpression Param (string t, string name)
328 return new CodeParameterDeclarationExpression (t, name);
331 private CodeParameterDeclarationExpression Param (Type t, string name)
333 return new CodeParameterDeclarationExpression (t, name);
336 private CodeParameterDeclarationExpression Param (CodeTypeReference t, string name)
338 return new CodeParameterDeclarationExpression (t, name);
341 private CodeArgumentReferenceExpression ParamRef (string name)
343 return new CodeArgumentReferenceExpression (name);
346 private CodeCastExpression Cast (string t, CodeExpression exp)
348 return new CodeCastExpression (t, exp);
351 private CodeCastExpression Cast (Type t, CodeExpression exp)
353 return new CodeCastExpression (t, exp);
356 private CodeCastExpression Cast (CodeTypeReference t, CodeExpression exp)
358 return new CodeCastExpression (t, exp);
361 private CodeExpression New (Type t, params CodeExpression [] parameters)
363 return new CodeObjectCreateExpression (t, parameters);
366 private CodeExpression New (string t, params CodeExpression [] parameters)
368 return new CodeObjectCreateExpression (TypeRef (t), parameters);
371 private CodeExpression NewArray (Type t, params CodeExpression [] parameters)
373 return new CodeArrayCreateExpression (t, parameters);
376 private CodeVariableReferenceExpression Local (string name)
378 return new CodeVariableReferenceExpression (name);
381 private CodeFieldReferenceExpression FieldRef (string name)
383 return new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), name);
386 private CodeFieldReferenceExpression FieldRef (CodeExpression exp, string name)
388 return new CodeFieldReferenceExpression (exp, name);
391 private CodePropertyReferenceExpression PropRef (string name)
393 return new CodePropertyReferenceExpression (new CodeThisReferenceExpression (), name);
396 private CodePropertyReferenceExpression PropRef (CodeExpression target, string name)
398 return new CodePropertyReferenceExpression (target, name);
401 private CodeIndexerExpression IndexerRef (CodeExpression target, CodeExpression parameters)
403 return new CodeIndexerExpression (target, parameters);
406 private CodeIndexerExpression IndexerRef (CodeExpression param)
408 return new CodeIndexerExpression (new CodeThisReferenceExpression (), param);
411 private CodeEventReferenceExpression EventRef (string name)
413 return new CodeEventReferenceExpression (new CodeThisReferenceExpression (), name);
416 private CodeEventReferenceExpression EventRef (CodeExpression target, string name)
418 return new CodeEventReferenceExpression (target, name);
421 private CodeMethodInvokeExpression MethodInvoke (string name, params CodeExpression [] parameters)
423 return new CodeMethodInvokeExpression (new CodeThisReferenceExpression (), name, parameters);
426 private CodeMethodInvokeExpression MethodInvoke (CodeExpression target, string name, params CodeExpression [] parameters)
428 return new CodeMethodInvokeExpression (target, name, parameters);
431 // note that this is "Identity" equality comparison
432 private CodeBinaryOperatorExpression Equals (CodeExpression exp1, CodeExpression exp2)
434 return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.IdentityEquality, exp2);
437 private CodeBinaryOperatorExpression Inequals (CodeExpression exp1, CodeExpression exp2)
439 return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.IdentityInequality, exp2);
442 private CodeTypeReferenceExpression TypeRefExp (Type t)
444 return new CodeTypeReferenceExpression (t);
448 private CodeExpressionStatement Eval (CodeExpression exp)
450 return new CodeExpressionStatement (exp);
453 private CodeAssignStatement Let (CodeExpression exp, CodeExpression value)
455 return new CodeAssignStatement (exp, value);
458 private CodeMethodReturnStatement Return (CodeExpression exp)
460 return new CodeMethodReturnStatement (exp);
463 private CodeVariableDeclarationStatement VarDecl (Type t,
464 string name, CodeExpression init)
466 return new CodeVariableDeclarationStatement (t, name, init);
469 private CodeVariableDeclarationStatement VarDecl (string t,
470 string name, CodeExpression init)
472 return new CodeVariableDeclarationStatement (t, name, init);
475 private CodeCommentStatement Comment (string comment)
477 return new CodeCommentStatement (comment);
480 private CodeThrowExceptionStatement Throw (CodeExpression exp)
482 return new CodeThrowExceptionStatement (exp);
485 #region DataSet class
487 private CodeTypeDeclaration GenerateDataSetType ()
489 // Type
490 dsType = new CodeTypeDeclaration (opts.DataSetName (ds.DataSetName, gen));
491 dsType.BaseTypes.Add (TypeRef (typeof (DataSet)));
493 // .ctor()
494 dsType.Members.Add (CreateDataSetDefaultCtor ());
495 // runtime serialization .ctor()
496 dsType.Members.Add (CreateDataSetSerializationCtor ());
498 // Clone()
499 dsType.Members.Add (CreateDataSetCloneMethod (dsType));
501 // FIXME: I keep these methods out of the generated source right now.
502 // It should be added after runtime serialization was implemented.
504 // ShouldSerializeTables()
505 dsType.Members.Add (CreateDataSetShouldSerializeTables ());
507 // ShouldSerializeRelations()
508 dsType.Members.Add (CreateDataSetShouldSerializeRelations ());
510 // ReadXmlSerializable()
511 dsType.Members.Add (CreateDataSetReadXmlSerializable ());
513 // GetSchemaSerializable()
514 dsType.Members.Add (CreateDataSetGetSchemaSerializable ());
516 dsType.Members.Add (CreateDataSetInitializeClass ());
517 dsType.Members.Add (CreateDataSetInitializeFields ());
518 dsType.Members.Add (CreateDataSetSchemaChanged ());
520 // table class and members
521 foreach (DataTable table in ds.Tables)
522 CreateDataSetTableMembers (dsType, table);
523 // relation class and members
524 foreach (DataRelation rel in ds.Relations)
525 CreateDataSetRelationMembers (dsType, rel);
527 return dsType;
530 // Code:
531 // public Foo ()
532 // {
533 // InitializeClass();
534 // CollectionChangeEventHandler handler = new CollectionChangeEventHandler (SchemaChanged);
535 // Tables.CollectionChanged += handler;
536 // Relations.CollectionChanged += handler;
537 // }
538 private CodeConstructor CreateDataSetDefaultCtor ()
540 CodeConstructor ctor = new CodeConstructor ();
541 ctor.Attributes = MemberAttributes.Public;
542 // Code: InitializeClass().
543 ctor.Statements.Add (Eval (MethodInvoke ("InitializeClass")));
545 // Code: CollectionChangedEventHandler handler = new CollectionChangeEventHandler (SchemeChanged);
546 CodeVariableDeclarationStatement stmt2 =
547 VarDecl (
548 typeof (CollectionChangeEventHandler),
549 "handler",
550 New (typeof (CollectionChangeEventHandler), FieldRef ("SchemaChanged")));
551 ctor.Statements.Add (stmt2);
553 // Code: Tables.CollectionChanged += handler;
554 ctor.Statements.Add (
555 new CodeAttachEventStatement (
556 EventRef (
557 PropRef ("Tables"),
558 "CollectionChanged"),
559 Local ("handler")));
561 // Code: Relations.CollectionChanged += handler;
562 ctor.Statements.Add (
563 new CodeAttachEventStatement (
564 EventRef (
565 PropRef ("Relations"),
566 "CollectionChanged"),
567 Local ("handler")));
569 return ctor;
572 // TODO: implement
574 // Code:
575 // protected Foo (SerializationInfo info, StreamingContext ctx)
576 // {
577 // throw new NotImplementedException ();
578 // }
579 private CodeConstructor CreateDataSetSerializationCtor ()
581 CodeConstructor ctor = new CodeConstructor ();
582 ctor.Attributes = MemberAttributes.Family;
583 ctor.Parameters.Add (Param (typeof (SerializationInfo), "info"));
584 ctor.Parameters.Add (Param (typeof (StreamingContext), "ctx"));
586 // Code:
587 // // TODO: implement
588 // throw new NotImplementedException ();
589 ctor.Statements.Add (Comment ("TODO: implement"));
590 ctor.Statements.Add (Throw (New (typeof (NotImplementedException))));
592 return ctor;
595 // Code:
596 // public override DataSet Clone()
597 // {
598 // [foo] set = ([foo]) base.Clone ();
599 // set.InitializeFields ();
600 // return set;
601 // }
602 private CodeMemberMethod CreateDataSetCloneMethod (CodeTypeDeclaration dsType)
604 CodeMemberMethod m = new CodeMemberMethod ();
605 m.ReturnType = TypeRef (typeof (DataSet));
606 m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
607 m.Name = "Clone";
608 // Code: [foo] set = ([foo]) base.Clone ();
609 CodeVariableReferenceExpression set = Local ("set");
610 m.Statements.Add (VarDecl (
611 dsType.Name,
612 "set",
613 Cast (
614 dsType.Name,
615 MethodInvoke (Base (), "Clone"))));
616 m.Statements.Add (Eval (MethodInvoke (set, "InitializeFields")));
617 m.Statements.Add (Return (set));
618 return m;
621 // Code:
622 // protected override bool ShouldSerializeTables ()
623 // {
624 // return true; // it should be false
625 // }
626 private CodeMemberMethod CreateDataSetShouldSerializeTables ()
628 CodeMemberMethod m = new CodeMemberMethod ();
629 m.Name = "ShouldSerializeTables";
630 m.ReturnType = TypeRef (typeof (bool));
631 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
632 // FIXME: set "false" after serialization .ctor() implementation
633 m.Statements.Add (Return (Const (true)));
634 return m;
637 // Code:
638 // protected override bool ShouldSerializeRelations ()
639 // {
640 // return true; // it should be false
641 // }
642 private CodeMemberMethod CreateDataSetShouldSerializeRelations ()
644 CodeMemberMethod m = new CodeMemberMethod ();
645 m.Name = "ShouldSerializeRelations";
646 m.ReturnType = TypeRef (typeof (bool));
647 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
648 // FIXME: set "false" after serialization .ctor() implementation
649 m.Statements.Add (Return (Const (true)));
650 return m;
653 // Code:
654 // protected override void ReadXmlSerializable()
655 // {
656 // // TODO: implement
657 // throw new NotImplementedException ();
658 // }
659 private CodeMemberMethod CreateDataSetReadXmlSerializable ()
661 CodeMemberMethod method = new CodeMemberMethod ();
662 method.Name = "ReadXmlSerializable";
663 method.Attributes = MemberAttributes.Family | MemberAttributes.Override;
664 method.Parameters.Add (Param (TypeRef (typeof (XmlReader)), "reader"));
665 // TODO: implemnet
666 method.Statements.Add (Comment ("TODO: implement"));
667 // Hey, how can I specify the constructor to invoke chained ctor with an empty parameter list!?
668 method.Statements.Add (Throw (New (typeof (NotImplementedException))));
669 return method;
672 private CodeMemberMethod CreateDataSetInitializeClass ()
674 CodeMemberMethod m = new CodeMemberMethod ();
675 m.Name = "InitializeClass";
676 m.Attributes = MemberAttributes.Assembly;
678 // dataset properties
679 m.Statements.Add (Let (PropRef ("DataSetName"), Const (ds.DataSetName)));
680 m.Statements.Add (Let (PropRef ("Prefix"), Const (ds.Prefix)));
681 m.Statements.Add (Let (PropRef ("Namespace"), Const (ds.Namespace)));
682 m.Statements.Add (Let (PropRef ("Locale"), New (typeof (CultureInfo), Const (ds.Locale.Name))));
683 m.Statements.Add (Let (PropRef ("CaseSensitive"), Const (ds.CaseSensitive)));
684 m.Statements.Add (Let (PropRef ("EnforceConstraints"), Const (ds.EnforceConstraints)));
686 // table
687 foreach (DataTable dt in ds.Tables) {
688 string tableFieldName = "__table" + opts.TableMemberName (dt.TableName, gen);
689 string tableTypeName = opts.TableTypeName (dt.TableName, gen);
690 m.Statements.Add (Let (FieldRef (tableFieldName), New (tableTypeName)));
691 m.Statements.Add (Eval (MethodInvoke (PropRef ("Tables"), "Add", FieldRef (tableFieldName))));
694 bool fkcExists = false;
695 bool ucExists = false;
696 foreach (DataTable dt in ds.Tables) {
697 string tname = "__table" + opts.TableMemberName (dt.TableName, gen);
698 foreach (Constraint c in dt.Constraints) {
699 UniqueConstraint uc = c as UniqueConstraint;
700 if (uc != null) {
701 if (!ucExists) {
702 m.Statements.Add (VarDecl (typeof (UniqueConstraint), "uc", null));
703 ucExists = true;
705 CreateUniqueKeyStatements (m, uc, tname);
706 continue;
708 ForeignKeyConstraint fkc = c as ForeignKeyConstraint;
709 if (fkc != null) {
710 if (!fkcExists) {
711 m.Statements.Add (VarDecl (typeof (ForeignKeyConstraint), "fkc", null));
712 fkcExists = true;
714 CreateForeignKeyStatements (m, fkc, tname);
716 // What if other cases? dunno. Just ignore ;-)
719 foreach (DataRelation rel in ds.Relations) {
720 string relName = opts.RelationName (rel.RelationName, gen);
721 ArrayList pcols = new ArrayList ();
722 foreach (DataColumn pcol in rel.ParentColumns)
723 pcols.Add (IndexerRef (PropRef (FieldRef ("__table" + opts.TableMemberName (rel.ParentTable.TableName, gen)), "Columns"), Const (pcol.ColumnName)));
725 ArrayList ccols = new ArrayList ();
726 foreach (DataColumn ccol in rel.ChildColumns)
727 ccols.Add (IndexerRef (PropRef (FieldRef ("__table" + opts.TableMemberName (rel.ChildTable.TableName, gen)), "Columns"), Const (ccol.ColumnName)));
729 // relation field
730 string fieldName = "__relation" + relName;
731 m.Statements.Add (Let (FieldRef (fieldName), New (typeof (DataRelation),
732 Const (rel.RelationName),
733 NewArray (typeof (DataColumn), pcols.ToArray (typeof (CodeExpression)) as CodeExpression []),
734 NewArray (typeof (DataColumn), ccols.ToArray (typeof (CodeExpression)) as CodeExpression []),
735 Const (false)
736 )));
737 m.Statements.Add (Let (PropRef (FieldRef (fieldName), "Nested"), Const (rel.Nested)));
740 return m;
743 private void CreateUniqueKeyStatements (CodeMemberMethod m, UniqueConstraint uc, string tableField)
745 ArrayList al = new ArrayList ();
746 foreach (DataColumn col in uc.Columns)
747 al.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
749 m.Statements.Add (Let (Local ("uc"), New (
750 typeof (UniqueConstraint),
751 Const (uc.ConstraintName),
752 NewArray (
753 typeof (DataColumn),
754 al.ToArray (typeof (CodeExpression)) as CodeExpression []),
755 Const (uc.IsPrimaryKey))));
756 m.Statements.Add (MethodInvoke (PropRef (FieldRef (tableField), "Constraints"), "Add", Local ("uc")));
759 private void CreateForeignKeyStatements (CodeMemberMethod m,ForeignKeyConstraint fkc, string tableField)
761 ArrayList pcols = new ArrayList ();
762 foreach (DataColumn col in fkc.Columns)
763 pcols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
765 ArrayList ccols = new ArrayList ();
766 foreach (DataColumn col in fkc.RelatedColumns)
767 pcols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
769 m.Statements.Add (Let (Local ("fkc"), New (
770 typeof (ForeignKeyConstraint),
771 Const (fkc.ConstraintName),
772 NewArray (
773 typeof (DataColumn),
774 pcols.ToArray (typeof (CodeExpression)) as CodeExpression []),
775 NewArray (
776 typeof (DataColumn),
777 ccols.ToArray (typeof (CodeExpression)) as CodeExpression []))));
779 m.Statements.Add (Let (
780 PropRef (Local ("fkc"), "AcceptRejectRule"),
781 FieldRef (TypeRefExp (typeof (AcceptRejectRule)), Enum.GetName (typeof (AcceptRejectRule), fkc.AcceptRejectRule))));
782 m.Statements.Add (Let (
783 PropRef (Local ("fkc"), "DeleteRule"),
784 FieldRef (TypeRefExp (typeof (Rule)), Enum.GetName (typeof (Rule), fkc.DeleteRule))));
785 m.Statements.Add (Let (
786 PropRef (Local ("fkc"), "UpdateRule"),
787 FieldRef (TypeRefExp (typeof (Rule)), Enum.GetName (typeof (Rule), fkc.UpdateRule))));
789 m.Statements.Add (MethodInvoke (PropRef (FieldRef (tableField), "Constraints"), "Add", Local ("fkc")));
792 private CodeMemberMethod CreateDataSetInitializeFields ()
794 CodeMemberMethod m = new CodeMemberMethod ();
795 m.Attributes = MemberAttributes.Assembly;
796 m.Name = "InitializeFields";
798 foreach (DataTable dt in ds.Tables)
799 m.Statements.Add (Eval (MethodInvoke (FieldRef ("__table" + opts.TableMemberName (dt.TableName, gen)), "InitializeFields")));
801 foreach (DataRelation rel in ds.Relations)
802 m.Statements.Add (Let (FieldRef ("__relation" + opts.RelationName (rel.RelationName, gen)), IndexerRef (PropRef ("Relations"), Const (rel.RelationName))));
804 return m;
807 private CodeMemberMethod CreateDataSetSchemaChanged ()
809 CodeMemberMethod m = new CodeMemberMethod ();
810 m.Name = "SchemaChanged";
811 m.Parameters.Add (Param (typeof (object), "sender"));
812 m.Parameters.Add (Param (typeof (CollectionChangeEventArgs), "e"));
814 m.Statements.Add (
815 new CodeConditionStatement (
816 Equals (
817 PropRef (ParamRef ("e"), "Action"),
818 FieldRef (TypeRefExp (typeof (CollectionChangeAction)), "Remove")),
819 new CodeStatement [] { Eval (MethodInvoke ("InitializeFields")) },
820 new CodeStatement [] {}));
821 return m;
824 private void CreateDataSetTableMembers (CodeTypeDeclaration dsType, DataTable table)
826 string tableTypeName = opts.TableTypeName (table.TableName, gen);
827 string tableVarName = opts.TableMemberName (table.TableName, gen);
829 CodeMemberField privTable = new CodeMemberField ();
830 privTable.Type = TypeRef (tableTypeName);
831 privTable.Name = "__table" + tableVarName;
832 dsType.Members.Add (privTable);
834 CodeMemberProperty pubTable = new CodeMemberProperty ();
835 pubTable.Type = TypeRef (tableTypeName);
836 pubTable.Attributes = MemberAttributes.Public;
837 pubTable.Name = tableVarName;
838 pubTable.HasSet = false;
839 // Code: return __table[foo];
840 pubTable.GetStatements.Add (Return (FieldRef ("__table" + tableVarName)));
842 dsType.Members.Add (pubTable);
846 private void CreateDataSetRelationMembers (CodeTypeDeclaration dsType, DataRelation relation)
848 string relName = opts.RelationName (relation.RelationName, gen);
849 string fieldName = "__relation" + relName;
851 CodeMemberField field = new CodeMemberField ();
852 field.Type = TypeRef (typeof (DataRelation));
853 field.Name = fieldName;
854 dsType.Members.Add (field);
856 // This is not supported in MS.NET
857 CodeMemberProperty prop = new CodeMemberProperty ();
858 prop.Type = TypeRef (typeof (DataRelation));
859 prop.Attributes = MemberAttributes.Public;
860 prop.Name = relName;
861 prop.HasSet = false;
862 // Code: return __relation[foo_bar];
863 prop.GetStatements.Add (Return (FieldRef (fieldName)));
864 dsType.Members.Add (prop);
867 #endregion
871 #region DataTable class
873 private CodeTypeDeclaration GenerateDataTableType (DataTable dt)
875 CodeTypeDeclaration t = new CodeTypeDeclaration ();
876 t.Name = opts.TableTypeName (dt.TableName, gen);
877 t.BaseTypes.Add (TypeRef (typeof (DataTable)));
878 t.BaseTypes.Add (TypeRef (typeof (IEnumerable)));
880 t.Members.Add (CreateTableCtor1 (dt));
881 t.Members.Add (CreateTableCtor2 (dt));
883 t.Members.Add (CreateTableCount (dt));
884 t.Members.Add (CreateTableIndexer (dt));
886 t.Members.Add (CreateTableInitializeClass (dt));
887 t.Members.Add (CreateTableInitializeFields (dt));
889 t.Members.Add (CreateTableGetEnumerator (dt));
890 t.Members.Add (CreateTableClone (dt));
891 t.Members.Add (CreateTableCreateInstance (dt));
893 t.Members.Add (CreateTableAddRow1 (dt));
894 t.Members.Add (CreateTableAddRow2 (dt));
895 t.Members.Add (CreateTableNewRow (dt));
896 t.Members.Add (CreateTableNewRowFromBuilder (dt));
897 t.Members.Add (CreateTableRemoveRow (dt));
898 t.Members.Add (CreateTableGetRowType (dt));
900 t.Members.Add (CreateTableEventStarter (dt, "Changing"));
901 t.Members.Add (CreateTableEventStarter (dt, "Changed"));
902 t.Members.Add (CreateTableEventStarter (dt, "Deleting"));
903 t.Members.Add (CreateTableEventStarter (dt, "Deleted"));
905 // events
906 t.Members.Add (CreateTableEvent (dt, "RowChanging"));
907 t.Members.Add (CreateTableEvent (dt, "RowChanged"));
908 t.Members.Add (CreateTableEvent (dt, "RowDeleting"));
909 t.Members.Add (CreateTableEvent (dt, "RowDeleted"));
911 // column members
912 foreach (DataColumn col in dt.Columns) {
913 t.Members.Add (CreateTableColumnField (dt, col));
914 t.Members.Add (CreateTableColumnProperty (dt, col));
917 return t;
920 // Code:
921 // internal [foo]DataTable () : base ("[foo]")
922 // {
923 // InitializeClass ();
924 // }
925 private CodeConstructor CreateTableCtor1 (DataTable dt)
927 CodeConstructor c = new CodeConstructor ();
928 c.Attributes = MemberAttributes.Assembly;
929 c.BaseConstructorArgs.Add (Const (dt.TableName));
930 c.Statements.Add (Eval (MethodInvoke ("InitializeClass")));
931 c.Statements.Add (Eval (MethodInvoke ("InitializeFields")));
932 return c;
935 // Code:
936 // internal [foo]DataTable (DataTable table) : base (table.TableName)
937 // {
938 // // TODO: implement
939 // throw new NotImplementedException ();
940 // }
941 private CodeConstructor CreateTableCtor2 (DataTable dt)
943 CodeConstructor c = new CodeConstructor ();
944 c.Attributes = MemberAttributes.Assembly;
945 c.Parameters.Add (Param (typeof (DataTable), "table"));
946 c.BaseConstructorArgs.Add (PropRef (ParamRef ("table"), "TableName"));
947 // TODO: implement
948 c.Statements.Add (Comment ("TODO: implement"));
949 c.Statements.Add (Throw (New (typeof (NotImplementedException))));
950 return c;
953 private CodeMemberMethod CreateTableInitializeClass (DataTable dt)
955 CodeMemberMethod m = new CodeMemberMethod ();
956 m.Name = "InitializeClass";
957 foreach (DataColumn col in dt.Columns) {
958 m.Statements.Add (Eval (MethodInvoke (
959 PropRef ("Columns"),
960 "Add",
961 New (typeof (DataColumn),
962 Const (col.ColumnName),
963 new CodeTypeOfExpression (col.DataType)
964 ))));
966 return m;
969 private CodeMemberMethod CreateTableInitializeFields (DataTable dt)
971 CodeMemberMethod m = new CodeMemberMethod ();
972 m.Name = "InitializeFields";
973 m.Attributes = MemberAttributes.Assembly;
974 foreach (DataColumn col in dt.Columns)
975 m.Statements.Add (Let (FieldRef ("__column" + opts.TableColName (col.ColumnName, gen)), IndexerRef (PropRef ("Columns"), Const (col.ColumnName))));
976 return m;
979 private CodeMemberMethod CreateTableClone (DataTable dt)
981 CodeMemberMethod m = new CodeMemberMethod ();
982 m.Name = "Clone";
983 m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
984 m.ReturnType = TypeRef (typeof (DataTable));
985 string typeName = opts.TableTypeName (dt.TableName, gen);
986 m.Statements.Add (
987 VarDecl (typeName, "t", Cast (typeName, MethodInvoke (Base (), "Clone"))));
988 m.Statements.Add (Eval (MethodInvoke (Local ("t"), "InitializeFields")));
989 m.Statements.Add (Return (Local ("t")));
990 return m;
993 private CodeMemberMethod CreateTableGetEnumerator (DataTable dt)
995 CodeMemberMethod m = new CodeMemberMethod ();
996 m.Name = "GetEnumerator";
997 m.Attributes = MemberAttributes.Public;
998 m.ReturnType = TypeRef (typeof (IEnumerator));
999 m.Statements.Add (Return (MethodInvoke (PropRef ("Rows"), "GetEnumerator")));
1000 return m;
1003 private CodeMemberMethod CreateTableCreateInstance (DataTable dt)
1005 CodeMemberMethod m = new CodeMemberMethod ();
1006 m.Name = "CreateInstance";
1007 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1008 m.ReturnType = TypeRef (typeof (DataTable));
1009 m.Statements.Add (Return (New (opts.TableTypeName (dt.TableName, gen))));
1010 return m;
1013 private CodeMemberField CreateTableColumnField (DataTable dt, DataColumn col)
1015 CodeMemberField f = new CodeMemberField ();
1016 f.Name = "__column" + opts.ColumnName (col.ColumnName, gen);
1017 f.Type = TypeRef (typeof (DataColumn));
1018 return f;
1021 private CodeMemberProperty CreateTableColumnProperty (DataTable dt, DataColumn col)
1023 string name = opts.ColumnName (col.ColumnName, gen);
1024 CodeMemberProperty p = new CodeMemberProperty ();
1025 p.Name = name + "Column";
1026 p.Attributes = MemberAttributes.Assembly;
1027 p.Type = TypeRef (typeof (DataColumn));
1028 p.HasSet = false;
1029 p.GetStatements.Add (Return (FieldRef ("__column" + name)));
1030 return p;
1033 private CodeMemberProperty CreateTableCount (DataTable dt)
1035 CodeMemberProperty p = new CodeMemberProperty ();
1036 p.Name = "Count";
1037 p.Attributes = MemberAttributes.Public;
1038 p.Type = TypeRef (typeof (int));
1039 p.HasSet = false;
1040 p.GetStatements.Add (Return (PropRef (PropRef ("Rows"), "Count")));
1041 return p;
1044 private CodeMemberProperty CreateTableIndexer (DataTable dt)
1046 string rowName = opts.RowName (dt.TableName, gen);
1047 CodeMemberProperty ix = new CodeMemberProperty ();
1048 ix.Name = "Item"; // indexer
1049 ix.Attributes = MemberAttributes.Public;
1050 ix.Type = TypeRef (rowName);
1051 ix.Parameters.Add (Param (typeof (int), "i"));
1052 ix.HasSet = false;
1053 ix.GetStatements.Add (Return (Cast (rowName, IndexerRef (PropRef ("Rows"), ParamRef ("i")))));
1054 return ix;
1057 private CodeMemberMethod CreateTableAddRow1 (DataTable dt)
1059 CodeMemberMethod m = new CodeMemberMethod ();
1060 string rowType = opts.RowName (dt.TableName, gen);
1061 m.Name = "Add" + rowType;
1062 m.Attributes = MemberAttributes.Public;
1063 m.Parameters.Add (Param (TypeRef (rowType), "row"));
1064 m.Statements.Add (Eval (MethodInvoke (PropRef ("Rows"), "Add", ParamRef ("row"))));
1065 return m;
1068 private CodeMemberMethod CreateTableAddRow2 (DataTable dt)
1070 CodeMemberMethod m = new CodeMemberMethod ();
1071 string rowType = opts.RowName (dt.TableName, gen);
1072 m.Name = "Add" + rowType;
1073 m.ReturnType = TypeRef (rowType);
1074 m.Attributes = MemberAttributes.Public;
1076 m.Statements.Add (VarDecl (rowType, "row", MethodInvoke ("New" + rowType)));
1078 foreach (DataColumn col in dt.Columns) {
1079 if (col.ColumnMapping == MappingType.Hidden) {
1080 foreach (DataRelation r in dt.DataSet.Relations) {
1081 if (r.ChildTable == dt) {
1082 // parameter
1083 string paramType = opts.RowName (r.ParentTable.TableName, gen);
1084 string paramName = paramType;
1085 m.Parameters.Add (Param (paramType, paramName));
1086 // CODE: SetParentRow (fooRow, DataSet.Relations ["foo_bar"]);
1087 m.Statements.Add (Eval (MethodInvoke (Local ("row"), "SetParentRow", ParamRef (paramName), IndexerRef (PropRef (PropRef ("DataSet"), "Relations"), Const (r.RelationName)))));
1088 break;
1092 else {
1093 // parameter
1094 string paramName = opts.ColumnName (col.ColumnName, gen);
1095 m.Parameters.Add (Param (col.DataType, paramName));
1096 // row ["foo"] = foo;
1097 m.Statements.Add (Let (IndexerRef (Local ("row"), Const (paramName)), ParamRef (paramName)));
1101 // Rows.Add (row);
1102 m.Statements.Add (MethodInvoke (PropRef ("Rows"), "Add", Local ("row")));
1103 m.Statements.Add (Return (Local ("row")));
1105 return m;
1108 private CodeMemberMethod CreateTableNewRow (DataTable dt)
1110 CodeMemberMethod m = new CodeMemberMethod ();
1111 string rowType = opts.RowName (dt.TableName, gen);
1112 m.Name = "New" + rowType;
1113 m.ReturnType = TypeRef (rowType);
1114 m.Attributes = MemberAttributes.Public;
1115 m.Statements.Add (Return (Cast (rowType, MethodInvoke ("NewRow"))));
1116 return m;
1119 private CodeMemberMethod CreateTableNewRowFromBuilder (DataTable dt)
1121 CodeMemberMethod m = new CodeMemberMethod ();
1122 m.Name = "NewRowFromBuilder";
1123 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1124 m.ReturnType = TypeRef (typeof (DataRow));
1125 m.Parameters.Add (Param (typeof (DataRowBuilder), "builder"));
1126 m.Statements.Add (Return (New (opts.RowName (dt.TableName, gen), ParamRef ("builder"))));
1127 return m;
1130 private CodeMemberMethod CreateTableRemoveRow (DataTable dt)
1132 CodeMemberMethod m = new CodeMemberMethod ();
1133 string rowType = opts.RowName (dt.TableName, gen);
1134 m.Name = "Remove" + rowType;
1135 m.Attributes = MemberAttributes.Public;
1136 m.Parameters.Add (Param (TypeRef (rowType), "row"));
1137 m.Statements.Add (Eval (MethodInvoke (PropRef ("Rows"), "Remove", ParamRef ("row"))));
1138 return m;
1141 private CodeMemberMethod CreateTableGetRowType (DataTable dt)
1143 CodeMemberMethod m = new CodeMemberMethod ();
1144 m.Name = "GetRowType";
1145 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1146 m.ReturnType = TypeRef (typeof (Type));
1147 m.Statements.Add (Return (new CodeTypeOfExpression (opts.RowName (dt.TableName, gen))));
1148 return m;
1151 private CodeMemberMethod CreateTableEventStarter (DataTable dt, string type)
1153 CodeMemberMethod m = new CodeMemberMethod ();
1154 m.Name = "OnRow" + type;
1155 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1156 m.Parameters.Add (Param (typeof (DataRowChangeEventArgs), "e"));
1158 m.Statements.Add (Eval (MethodInvoke (
1159 Base (),
1160 m.Name,
1161 ParamRef ("e"))));
1162 string eventName = opts.TableMemberName (dt.TableName, gen) + "Row" + type;
1163 CodeStatement trueStmt = Eval (
1164 MethodInvoke (
1165 eventName,
1166 This (),
1167 New (
1168 opts.EventArgsName (dt.TableName, gen),
1169 Cast (opts.RowName (dt.TableName, gen), PropRef (ParamRef ("e"), "Row")),
1170 PropRef (ParamRef ("e"), "Action"))));
1172 m.Statements.Add (
1173 new CodeConditionStatement (
1174 Inequals (EventRef (eventName), Const (null)),
1175 new CodeStatement [] {trueStmt},
1176 new CodeStatement [] {}));
1178 return m;
1181 private CodeMemberEvent CreateTableEvent (DataTable dt, string nameSuffix)
1183 CodeMemberEvent cme = new CodeMemberEvent ();
1184 cme.Attributes = MemberAttributes.Public;
1185 cme.Name = opts.TableMemberName (dt.TableName, gen) + nameSuffix;
1186 cme.Type = TypeRef (opts.TableDelegateName (dt.TableName, gen));
1187 return cme;
1190 #endregion
1194 #region Row class
1196 public CodeTypeDeclaration GenerateDataRowType (DataTable dt)
1198 CodeTypeDeclaration t = new CodeTypeDeclaration ();
1199 t.Name = opts.RowName (dt.TableName, gen);
1200 t.BaseTypes.Add (TypeRef (typeof (DataRow)));
1202 t.Members.Add (CreateRowCtor (dt));
1204 t.Members.Add (CreateRowTableField (dt));
1206 foreach (DataColumn col in dt.Columns) {
1207 if (col.ColumnMapping != MappingType.Hidden) {
1208 t.Members.Add (CreateRowColumnProperty (dt, col));
1209 t.Members.Add (CreateRowColumnIsNull (dt, col));
1210 t.Members.Add (CreateRowColumnSetNull (dt, col));
1214 foreach (DataRelation rel in dt.ParentRelations)
1215 t.Members.Add (CreateRowParentRowProperty (dt, rel));
1216 foreach (DataRelation rel in dt.ChildRelations)
1217 t.Members.Add (CreateRowGetChildRows (dt, rel));
1219 return t;
1222 private CodeConstructor CreateRowCtor (DataTable dt)
1224 CodeConstructor c = new CodeConstructor ();
1225 c.Attributes = MemberAttributes.Assembly;
1226 c.Parameters.Add (Param (typeof (DataRowBuilder), "builder"));
1227 c.BaseConstructorArgs.Add (ParamRef ("builder"));
1228 c.Statements.Add (Let (FieldRef ("table"), Cast (
1229 opts.TableTypeName (dt.TableName, gen),
1230 PropRef ("Table"))));
1231 return c;
1234 private CodeMemberField CreateRowTableField (DataTable dt)
1236 CodeMemberField f = new CodeMemberField ();
1237 f.Name = "table";
1238 f.Type = TypeRef (opts.TableTypeName (dt.TableName, gen));
1239 return f;
1242 private CodeMemberProperty CreateRowColumnProperty (DataTable dt, DataColumn col)
1244 CodeMemberProperty p = new CodeMemberProperty ();
1245 p.Name = opts.ColumnName (col.ColumnName, gen);
1246 p.Type = TypeRef (col.DataType);
1247 p.Attributes = MemberAttributes.Public;
1249 // This part should be better than MS code output.
1250 // Code:
1251 // object ret = this [col];
1252 // if (ret == DBNull.Value)
1253 // throw new StrongTypingException ()
1254 // else
1255 // return (type) ret;
1256 p.GetStatements.Add (VarDecl (typeof (object), "ret",
1257 IndexerRef (PropRef
1258 (PropRef ("table"),
1259 opts.TableColName (col.ColumnName, gen) + "Column"))));
1260 p.GetStatements.Add (new CodeConditionStatement (
1261 Equals (
1262 Local ("ret"),
1263 PropRef (TypeRefExp (typeof (DBNull)), "Value")),
1264 new CodeStatement [] {
1265 Throw (New (typeof (StrongTypingException), Const ("Cannot get strong typed value since it is DB null."), Const (null))) },
1266 new CodeStatement [] {
1267 Return (Cast (col.DataType, Local ("ret"))) }));
1269 p.SetStatements.Add (Let (IndexerRef (PropRef (PropRef ("table"), opts.TableColName (col.ColumnName, gen) + "Column")), new CodePropertySetValueReferenceExpression ()));
1271 return p;
1274 private CodeMemberMethod CreateRowColumnIsNull (DataTable dt, DataColumn col)
1276 CodeMemberMethod m = new CodeMemberMethod ();
1277 m.Name = "Is" + opts.ColumnName (col.ColumnName, gen) + "Null";
1278 m.Attributes = MemberAttributes.Public;
1279 m.ReturnType = TypeRef (typeof (bool));
1280 m.Statements.Add (Return (MethodInvoke (
1281 "IsNull",
1282 // table[foo].[bar]Column
1283 PropRef (
1284 PropRef ("table"),
1285 opts.TableColName (col.ColumnName, gen) + "Column"))));
1286 return m;
1289 private CodeMemberMethod CreateRowColumnSetNull (DataTable dt, DataColumn col)
1291 CodeMemberMethod m = new CodeMemberMethod ();
1292 m.Name = "Set" + opts.ColumnName (col.ColumnName, gen) + "Null";
1293 m.Attributes = MemberAttributes.Public;
1294 m.Statements.Add (Let (IndexerRef (
1295 PropRef (
1296 PropRef ("table"),
1297 opts.TableColName (col.ColumnName, gen) + "Column")),
1298 PropRef (TypeRefExp (typeof (DBNull)), "Value")));
1300 return m;
1303 private CodeMemberProperty CreateRowParentRowProperty (DataTable dt, DataRelation rel)
1305 CodeMemberProperty p = new CodeMemberProperty ();
1306 p.Name = opts.TableMemberName (rel.ParentTable.TableName, gen) + "Row";
1307 p.Attributes = MemberAttributes.Public;
1308 p.Type = TypeRef (opts.RowName (rel.ParentTable.TableName, gen));
1309 p.GetStatements.Add (Return (Cast (p.Type, MethodInvoke (
1310 "GetParentRow",
1311 IndexerRef (
1312 PropRef (
1313 PropRef (
1314 PropRef ("Table"),
1315 "DataSet"),
1316 "Relations"),
1317 Const (rel.RelationName))))));
1318 p.SetStatements.Add (Eval (MethodInvoke (
1319 "SetParentRow",
1320 new CodePropertySetValueReferenceExpression (),
1321 IndexerRef (
1322 PropRef (
1323 PropRef (
1324 PropRef ("Table"),
1325 "DataSet"),
1326 "Relations"),
1327 Const (rel.RelationName)))));
1329 return p;
1332 private CodeMemberMethod CreateRowGetChildRows (DataTable dt, DataRelation rel)
1334 CodeMemberMethod m = new CodeMemberMethod ();
1335 m.Name = "Get" + opts.TableMemberName (rel.ChildTable.TableName, gen) + "Rows";
1336 m.Attributes = MemberAttributes.Public;
1337 m.ReturnType = new CodeTypeReference (opts.RowName (rel.ChildTable.TableName, gen), 1);
1338 m.Statements.Add (Return (Cast (m.ReturnType, MethodInvoke (
1339 "GetChildRows",
1340 IndexerRef (
1341 PropRef (
1342 PropRef (
1343 PropRef ("Table"),
1344 "DataSet"),
1345 "Relations"),
1346 Const (rel.RelationName))))));
1347 return m;
1350 #endregion
1353 #region Event class
1355 // Code:
1356 // public class [foo]ChangeEventArgs : EventArgs
1357 // {
1358 // private [foo]Row row;
1359 // private DataRowAction action;
1360 // (.ctor())
1361 // (Row)
1362 // (Action)
1363 // }
1364 private CodeTypeDeclaration GenerateEventType (DataTable dt)
1366 CodeTypeDeclaration t = new CodeTypeDeclaration ();
1367 t.Name = opts.EventArgsName (dt.TableName, gen);
1368 t.BaseTypes.Add (TypeRef (typeof (EventArgs)));
1369 t.Attributes = MemberAttributes.Public;
1371 t.Members.Add (
1372 new CodeMemberField (
1373 TypeRef (opts.RowName (dt.TableName, gen)),
1374 "row"));
1375 t.Members.Add (
1376 new CodeMemberField (
1377 TypeRef (typeof (DataRowAction)), "action"));
1378 t.Members.Add (CreateEventCtor (dt));
1380 t.Members.Add (CreateEventRow (dt));
1382 t.Members.Add (CreateEventAction (dt));
1384 return t;
1387 // Code:
1388 // public [foo]RowChangeEventArgs ([foo]Row r, DataRowAction a)
1389 // {
1390 // row = r;
1391 // action = a;
1392 // }
1393 private CodeConstructor CreateEventCtor (DataTable dt)
1395 CodeConstructor c = new CodeConstructor ();
1396 c.Attributes = MemberAttributes.Public;
1397 c.Parameters.Add (Param (TypeRef (opts.RowName (dt.TableName, gen)), "r"));
1398 c.Parameters.Add (Param (TypeRef (typeof (DataRowAction)), "a"));
1399 c.Statements.Add (Let (FieldRef ("row"), ParamRef ("r")));
1400 c.Statements.Add (Let (FieldRef ("action"), ParamRef ("a")));
1402 return c;
1405 // Code:
1406 // public [foo]Row Row {
1407 // get { return row; }
1408 // }
1409 private CodeMemberProperty CreateEventRow (DataTable dt)
1411 CodeMemberProperty p = new CodeMemberProperty ();
1412 p.Name = "Row";
1413 p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
1414 p.Type = TypeRef (opts.RowName (dt.TableName, gen));
1415 p.HasSet = false;
1416 p.GetStatements.Add (Return (FieldRef ("row")));
1417 return p;
1420 // Code:
1421 // public DataRowAction Action {
1422 // get { return action; }
1423 // }
1424 private CodeMemberProperty CreateEventAction (DataTable dt)
1426 CodeMemberProperty p = new CodeMemberProperty ();
1427 p.Name = "Action";
1428 p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
1429 p.Type = TypeRef (typeof (DataRowAction));
1430 p.HasSet = false;
1431 p.GetStatements.Add (Return (FieldRef ("action")));
1432 return p;
1435 #endregion
1441 /* =========================================================
1444 MonoDataSetGenerator API notes
1447 ** generator API:
1448 CreateDataSetClasses (
1449 DataSet ds,
1450 CodeNamespace cns,
1451 ICodeGenerator gen,
1452 GeneratorOptions options)
1454 ** classes:
1456 *** Code naming method delegate
1458 public delegate string CodeNamingMethod (string sourceName);
1460 It is used in CodeGeneratorOptions (describled immediately below).
1464 *** Generator Options
1466 public bool MakeClassesInsideDataSet
1467 indicates whether classes and delegates other than DataSet
1468 itself are "contained" in the DataSet class or not.
1470 public CodeNamingMethod CreateDataSetName;
1471 public CodeNamingMethod CreateTableTypeName;
1472 public CodeNamingMethod CreateTableMemberName;
1473 public CodeNamingMethod CreateColumnName;
1474 public CodeNamingMethod CreateRowName;
1475 public CodeNamingMethod CreateRelationName;
1476 public CodeNamingMethod CreateTableDelegateName;
1477 public CodeNamingMethod CreateEventArgsName;
1478 Custom methods each of that returns type or member name.
1480 By default, they are set as to useTypedDataSetGenerator.
1481 CreateIdName() with modifications listed as below:
1483 DataSetName: as is
1484 TableTypeName: "DataTable" suffix
1485 TableMemberName: as is
1486 ColumnName: as is
1487 RowName: "Row" suffix
1488 RelationName: (TBD; maybe had better have another delegate type)
1489 DelegateName: "RowChangedEventHandler" suffix
1490 EventArgsName: "RowChangedEventArgs" suffix
1492 ** Auto Generated classes
1494 1. Custom DataSet class
1496 class name = dataset name, encoded by options.CreateDataSetName().
1498 *** .ctor
1500 public default .ctor()
1501 "initialize" class.
1502 set custom delegate on Tables.CollectionChanged
1503 set custom delegate on Relations.CollectionChanged
1505 runtime serialization .ctor()
1508 *** public members
1510 data tables: [foo]DataTable foo { return this.table[foo]; }
1512 Clone()
1513 init variables on new dataset.
1515 *** protected members
1517 ShouldSerializeTables()
1518 returns false, while default DataSet returns true.
1519 ShouldSerializeRelations()
1520 returns false, while default DataSet returns true.
1522 ReadXmlSerializable() ... similar to runtime serialization
1525 GetSchemaSerializable()
1526 Write its schema to temporary MemoryStream
1527 Read XML schema from the stream
1529 *** internal members
1531 "init variables"
1532 set member fields (tables, relations)
1533 call members' "init variables"
1535 "init class"
1536 set DataSetName, Prefix, Namespace, Locale, CaseSensitive, EnforceConstraints
1537 for each table
1538 allocate table[foo]
1539 Tables.Add()
1540 create FKC: new FKC([rel], new DataColumn [] {table[foo].[keyColumnName]Column}, new DataColumn [] {table[child].[childColName]Column}
1541 fill Rule properties.
1542 allocate relation[rel] and fill Nested, then Relations.Add()
1544 *** private members
1546 data tables: [foo]DataTable table[foo];
1548 data relations: DataRelation relation[rel];
1550 ShouldSerialize[foo]
1554 2. Custom DataTable classes for each DataTable
1556 This class is created under the dataset.
1558 *** internal members
1560 .ctor() : base("[foo]")
1561 initialize class
1563 .ctor(DataTable)
1564 wtf?
1566 DataColumn [bar]Column { return column[bar]; }
1568 "init variables"()
1569 fill each column fields
1571 *** public members
1573 int Count { rowcount }
1575 this [int index] { row [i]; }
1577 event [foo]RowChangedEventHandler [foo]RowChanged
1578 event [foo]RowChangedEventHandler [foo]RowChanging
1579 event [foo]RowChangedEventHandler [foo]RowDeleted
1580 event [foo]RowChangedEventHandler [foo]RowDeleting
1582 void Add[foo]Row ([foo]Row row) { Rows.Add (row); }
1584 [foo]Row Add[foo]Row ([columnType] [columnName])
1585 create new [foo]row.
1586 set members
1587 Rows.Add ()
1588 // where
1589 // non-relation-children are just created as column type
1590 // relation-children are typeof fooRow[]
1592 GetEnumerator() { Rows.GetEnumerator (); }
1594 override DataTable Clone()
1595 "init variables"
1597 [foo]Row New[foo]Row()
1599 void Remove[foo]Row([foo]Row)
1601 //for each ChildRelations
1602 [bar]Row [] Get[foo_bar]Rows ()
1604 *** protected members
1606 override DataTable CreateInstance() { return new }
1608 override DataRow NewRowFromBuilder(DataRowBuilder)
1610 override Type GetRowType()
1612 override void OnRowChanged(DataRowChangedEventArgs)
1613 base.()
1614 check this event [foo]RowChanged.
1616 override void OnRowChanging(DataRowChangedEventArgs)
1617 override void OnRowDeleted(DataRowChangedEventArgs)
1618 override void OnRowDeleting(DataRowChangedEventArgs)
1619 ... as well
1621 *** private members
1623 "initialize class"
1624 for each columns {
1625 column[bar] = new DataColumn (...);
1626 Columns.Add()
1629 DataColumn [bar]Column
1631 3. Custom DataRow classses
1633 *** public members
1635 for simple members:
1637 [bar_type] [bar] {
1638 get { try { } catch { throw StrongTypingException(); }
1639 set { this [[foo]Table.[bar]Column] = value; }
1641 bool Is[bar]Null ()
1642 IsNull ([foo]Table.[bar]Column);
1644 void Set[bar]Null ()
1646 if the table is parent of some relations
1648 public [child]Row [] Get[child]Rows()
1650 *** internal members
1652 .ctor(DataRowBuilder) : base.()
1653 table[foo] = Table;
1655 *** private members
1657 [foo]DataTable table[foo]
1660 4. Custom DataRowChangeEvent classes
1662 *** private members
1664 [foo]Row eventRow
1665 DataRowAction eventAction
1667 *** public members
1669 .ctor([foo]Row row, DataRowAction action)
1671 [foo]Row Row
1673 DataRowAction Action
1677 5. public Table RowChangedEventHandler delegates
1679 [foo]RowChangedEventHandler(object, [foo]RowChangedEvent e)
1682 ======================================================== */