2 // Mono.Data.CustomDataClassGenerator
5 // Atsushi Enomoto <atsushi@ximian.com>
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:
26 // The above copyright notice and this permission notice shall be
27 // included in all copies or substantial portions of the Software.
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.
40 using System.Collections;
42 using System.Globalization;
44 using System.CodeDom.Compiler;
45 using System.ComponentModel;
46 using System.Runtime.Serialization;
47 using System.Xml.Schema;
48 using System.Xml.Serialization;
51 using Microsoft.CSharp;
57 #if DATACLASS_GENERATOR_STANDALONE
60 public static void Main (string [] args)
63 if (args.Length < 1) {
64 Console.WriteLine ("mono dsgentest.exe filename");
68 DataSet ds = new DataSet ();
69 ds.ReadXml (args [0]);
70 ICodeGenerator gen = new CSharpCodeProvider ().CreateGenerator ();
72 CodeNamespace cns = new CodeNamespace ("MyNamespace");
73 TextWriter tw = new StreamWriter (Path.ChangeExtension (args [0], ".ms.cs"), false, Encoding.Default);
74 TypedDataSetGenerator.Generate (ds, cns, gen);
75 gen.GenerateCodeFromNamespace (cns, tw, null);
78 cns = new CodeNamespace ("MyNamespace");
79 tw = new StreamWriter (Path.ChangeExtension (args [0], ".mono.cs"), false, Encoding.Default);
80 CustomDataClassGenerator.CreateDataSetClasses (ds, cns, gen, null);
81 gen.GenerateCodeFromNamespace (cns, tw, null);
83 } catch (Exception ex) {
84 Console.WriteLine (ex);
90 #if DATACLASS_GENERATOR_STANDALONE
91 public class CustomDataClassGenerator
93 internal class CustomDataClassGenerator
96 public static void CreateDataSetClasses (DataSet ds,
97 CodeNamespace cns, ICodeGenerator gen,
98 ClassGeneratorOptions options)
100 new Generator (ds, cns, gen, options).Run ();
103 public static string MakeSafeName (string name, ICodeGenerator codeGen)
105 if (name == null || codeGen == null)
106 throw new NullReferenceException ();
108 name = codeGen.CreateValidIdentifier (name);
110 if (name.Length == 0)
113 StringBuilder sb = null;
114 if (!Char.IsLetter (name, 0) && name [0] != '_') {
115 sb = new StringBuilder ();
120 for (int i = 0; i < name.Length; i++) {
121 if (!Char.IsLetterOrDigit (name, i)) {
123 sb = new StringBuilder ();
124 sb.Append (name, start, i - start);
131 sb.Append (name, start, name.Length - start);
132 return sb.ToString ();
139 #if DATACLASS_GENERATOR_STANDALONE
140 public delegate string CodeNamingMethod (string source, ICodeGenerator gen);
142 internal delegate string CodeNamingMethod (string source, ICodeGenerator gen);
145 #if DATACLASS_GENERATOR_STANDALONE
146 public class ClassGeneratorOptions
148 internal class ClassGeneratorOptions
151 public bool MakeClassesInsideDataSet = true; // default = MS compatible
153 public CodeNamingMethod CreateDataSetName;
154 public CodeNamingMethod CreateTableTypeName;
155 public CodeNamingMethod CreateTableMemberName;
156 public CodeNamingMethod CreateTableColumnName;
157 public CodeNamingMethod CreateColumnName;
158 public CodeNamingMethod CreateRowName;
159 public CodeNamingMethod CreateRelationName;
160 public CodeNamingMethod CreateTableDelegateName;
161 public CodeNamingMethod CreateEventArgsName;
163 internal string DataSetName (string source, ICodeGenerator gen)
165 if (CreateDataSetName != null)
166 return CreateDataSetName (source, gen);
168 return CustomDataClassGenerator.MakeSafeName (source, gen);
171 internal string TableTypeName (string source, ICodeGenerator gen)
173 if (CreateTableTypeName != null)
174 return CreateTableTypeName (source, gen);
176 return CustomDataClassGenerator.MakeSafeName (source, gen) + "DataTable";
179 internal string TableMemberName (string source, ICodeGenerator gen)
181 if (CreateTableMemberName != null)
182 return CreateTableMemberName (source, gen);
184 return CustomDataClassGenerator.MakeSafeName (source, gen);
187 internal string TableColName (string source, ICodeGenerator gen)
189 if (CreateTableColumnName != null)
190 return CreateTableColumnName (source, gen);
192 return CustomDataClassGenerator.MakeSafeName (source, gen);
195 internal string TableDelegateName (string source, ICodeGenerator gen)
197 if (CreateTableDelegateName != null)
198 return CreateTableDelegateName (source, gen);
200 return CustomDataClassGenerator.MakeSafeName (source, gen) + "RowChangedEventHandler";
203 internal string EventArgsName (string source, ICodeGenerator gen)
205 if (CreateEventArgsName != null)
206 return CreateEventArgsName (source, gen);
208 return CustomDataClassGenerator.MakeSafeName (source, gen) + "RowChangedEventArgs";
211 internal string ColumnName (string source, ICodeGenerator gen)
213 if (CreateColumnName != null)
214 return CreateColumnName (source, gen);
216 return CustomDataClassGenerator.MakeSafeName (source, gen);
219 internal string RowName (string source, ICodeGenerator gen)
221 if (CreateRowName != null)
222 return CreateRowName (source, gen);
224 return CustomDataClassGenerator.MakeSafeName (source, gen) + "Row";
227 internal string RelationName (string source, ICodeGenerator gen)
229 if (CreateRelationName != null)
230 return CreateRelationName (source, gen);
232 return CustomDataClassGenerator.MakeSafeName (source, gen) + "Relation";
236 internal class Generator
238 static ClassGeneratorOptions DefaultOptions = new ClassGeneratorOptions ();
242 ClassGeneratorOptions opts;
245 CodeTypeDeclaration dsType;
247 public Generator (DataSet ds, CodeNamespace cns, ICodeGenerator gen, ClassGeneratorOptions options)
255 opts = DefaultOptions;
261 cns.Imports.Add (new CodeNamespaceImport ("System"));
262 cns.Imports.Add (new CodeNamespaceImport ("System.Collections"));
263 cns.Imports.Add (new CodeNamespaceImport ("System.ComponentModel"));
264 cns.Imports.Add (new CodeNamespaceImport ("System.Data"));
265 cns.Imports.Add (new CodeNamespaceImport ("System.Runtime.Serialization"));
266 cns.Imports.Add (new CodeNamespaceImport ("System.Xml"));
269 CodeTypeDeclaration dsType = GenerateDataSetType ();
270 cns.Types.Add (dsType);
271 foreach (DataTable dt in ds.Tables) {
272 // 1. table types ([foo]DataTable)
273 // 2. row types ([foo]Row)
274 // 3. delegates ([foo]RowChangedEventHandler)
275 // 4. eventargs ([foo]RowChangeEventArgs)
277 CodeTypeDeclaration dtType = GenerateDataTableType (dt);
279 CodeTypeDeclaration dtRow = GenerateDataRowType (dt);
281 CodeTypeDelegate dtDelegate = new CodeTypeDelegate (opts.TableDelegateName (dt.TableName, gen));
282 dtDelegate.Parameters.Add (Param (typeof (object), "o"));
283 dtDelegate.Parameters.Add (Param (opts.EventArgsName (dt.TableName, gen), "e"));
285 CodeTypeDeclaration dtEventType = GenerateEventType (dt);
287 // Add types to either DataSet or CodeNamespace
288 if (opts.MakeClassesInsideDataSet) {
289 dsType.Members.Add (dtType);
290 dsType.Members.Add (dtRow);
291 dsType.Members.Add (dtDelegate);
292 dsType.Members.Add (dtEventType);
295 cns.Types.Add (dtType);
296 cns.Types.Add (dtRow);
297 cns.Types.Add (dtDelegate);
298 cns.Types.Add (dtEventType);
303 private CodeThisReferenceExpression This ()
305 return new CodeThisReferenceExpression ();
308 private CodeBaseReferenceExpression Base ()
310 return new CodeBaseReferenceExpression ();
313 private CodePrimitiveExpression Const (object value)
315 return new CodePrimitiveExpression (value);
318 private CodeTypeReference TypeRef (Type t)
320 return new CodeTypeReference (t);
323 private CodeTypeReference TypeRef (string name)
325 return new CodeTypeReference (name);
328 private CodeParameterDeclarationExpression Param (string t, string name)
330 return new CodeParameterDeclarationExpression (t, name);
333 private CodeParameterDeclarationExpression Param (Type t, string name)
335 return new CodeParameterDeclarationExpression (t, name);
338 private CodeParameterDeclarationExpression Param (CodeTypeReference t, string name)
340 return new CodeParameterDeclarationExpression (t, name);
343 private CodeArgumentReferenceExpression ParamRef (string name)
345 return new CodeArgumentReferenceExpression (name);
348 private CodeCastExpression Cast (string t, CodeExpression exp)
350 return new CodeCastExpression (t, exp);
353 private CodeCastExpression Cast (Type t, CodeExpression exp)
355 return new CodeCastExpression (t, exp);
358 private CodeCastExpression Cast (CodeTypeReference t, CodeExpression exp)
360 return new CodeCastExpression (t, exp);
363 private CodeExpression New (Type t, params CodeExpression [] parameters)
365 return new CodeObjectCreateExpression (t, parameters);
368 private CodeExpression New (string t, params CodeExpression [] parameters)
370 return new CodeObjectCreateExpression (TypeRef (t), parameters);
373 private CodeExpression NewArray (Type t, params CodeExpression [] parameters)
375 return new CodeArrayCreateExpression (t, parameters);
378 private CodeVariableReferenceExpression Local (string name)
380 return new CodeVariableReferenceExpression (name);
383 private CodeFieldReferenceExpression FieldRef (string name)
385 return new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), name);
388 private CodeFieldReferenceExpression FieldRef (CodeExpression exp, string name)
390 return new CodeFieldReferenceExpression (exp, name);
393 private CodePropertyReferenceExpression PropRef (string name)
395 return new CodePropertyReferenceExpression (new CodeThisReferenceExpression (), name);
398 private CodePropertyReferenceExpression PropRef (CodeExpression target, string name)
400 return new CodePropertyReferenceExpression (target, name);
403 private CodeIndexerExpression IndexerRef (CodeExpression target, CodeExpression parameters)
405 return new CodeIndexerExpression (target, parameters);
408 private CodeIndexerExpression IndexerRef (CodeExpression param)
410 return new CodeIndexerExpression (new CodeThisReferenceExpression (), param);
413 private CodeEventReferenceExpression EventRef (string name)
415 return new CodeEventReferenceExpression (new CodeThisReferenceExpression (), name);
418 private CodeEventReferenceExpression EventRef (CodeExpression target, string name)
420 return new CodeEventReferenceExpression (target, name);
423 private CodeMethodInvokeExpression MethodInvoke (string name, params CodeExpression [] parameters)
425 return new CodeMethodInvokeExpression (new CodeThisReferenceExpression (), name, parameters);
428 private CodeMethodInvokeExpression MethodInvoke (CodeExpression target, string name, params CodeExpression [] parameters)
430 return new CodeMethodInvokeExpression (target, name, parameters);
433 // note that this is "Identity" equality comparison
434 private CodeBinaryOperatorExpression Equals (CodeExpression exp1, CodeExpression exp2)
436 return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.IdentityEquality, exp2);
439 private CodeBinaryOperatorExpression Inequals (CodeExpression exp1, CodeExpression exp2)
441 return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.IdentityInequality, exp2);
444 private CodeTypeReferenceExpression TypeRefExp (Type t)
446 return new CodeTypeReferenceExpression (t);
450 private CodeExpressionStatement Eval (CodeExpression exp)
452 return new CodeExpressionStatement (exp);
455 private CodeAssignStatement Let (CodeExpression exp, CodeExpression value)
457 return new CodeAssignStatement (exp, value);
460 private CodeMethodReturnStatement Return (CodeExpression exp)
462 return new CodeMethodReturnStatement (exp);
465 private CodeVariableDeclarationStatement VarDecl (Type t,
466 string name, CodeExpression init)
468 return new CodeVariableDeclarationStatement (t, name, init);
471 private CodeVariableDeclarationStatement VarDecl (string t,
472 string name, CodeExpression init)
474 return new CodeVariableDeclarationStatement (t, name, init);
477 private CodeCommentStatement Comment (string comment)
479 return new CodeCommentStatement (comment);
482 private CodeThrowExceptionStatement Throw (CodeExpression exp)
484 return new CodeThrowExceptionStatement (exp);
487 #region DataSet class
489 private CodeTypeDeclaration GenerateDataSetType ()
492 dsType = new CodeTypeDeclaration (opts.DataSetName (ds.DataSetName, gen));
493 dsType.BaseTypes.Add (TypeRef (typeof (DataSet)));
494 dsType.BaseTypes.Add (TypeRef (typeof (IXmlSerializable)));
497 dsType.Members.Add (CreateDataSetDefaultCtor ());
498 // runtime serialization .ctor()
499 dsType.Members.Add (CreateDataSetSerializationCtor ());
502 dsType.Members.Add (CreateDataSetCloneMethod (dsType));
504 // FIXME: I keep these methods out of the generated source right now.
505 // It should be added after runtime serialization was implemented.
507 // ShouldSerializeTables()
508 dsType.Members.Add (CreateDataSetShouldSerializeTables ());
510 // ShouldSerializeRelations()
511 dsType.Members.Add (CreateDataSetShouldSerializeRelations ());
513 // ReadXmlSerializable()
514 dsType.Members.Add (CreateDataSetReadXmlSerializable ());
517 // GetSchemaSerializable()
518 dsType.Members.Add (CreateDataSetGetSchemaSerializable ());
520 dsType.Members.Add (CreateDataSetGetSchema ());
521 dsType.Members.Add (CreateDataSetInitializeClass ());
522 dsType.Members.Add (CreateDataSetInitializeFields ());
523 dsType.Members.Add (CreateDataSetSchemaChanged ());
525 // table class and members
526 foreach (DataTable table in ds.Tables)
527 CreateDataSetTableMembers (dsType, table);
528 // relation class and members
529 foreach (DataRelation rel in ds.Relations)
530 CreateDataSetRelationMembers (dsType, rel);
538 // InitializeClass();
539 // CollectionChangeEventHandler handler = new CollectionChangeEventHandler (SchemaChanged);
540 // Tables.CollectionChanged += handler;
541 // Relations.CollectionChanged += handler;
543 private CodeConstructor CreateDataSetDefaultCtor ()
545 CodeConstructor ctor = new CodeConstructor ();
546 ctor.Attributes = MemberAttributes.Public;
547 // Code: InitializeClass().
548 ctor.Statements.Add (Eval (MethodInvoke ("InitializeClass")));
550 // Code: CollectionChangedEventHandler handler = new CollectionChangeEventHandler (SchemeChanged);
551 CodeVariableDeclarationStatement stmt2 =
553 typeof (CollectionChangeEventHandler),
555 New (typeof (CollectionChangeEventHandler), FieldRef ("SchemaChanged")));
556 ctor.Statements.Add (stmt2);
558 // Code: Tables.CollectionChanged += handler;
559 ctor.Statements.Add (
560 new CodeAttachEventStatement (
563 "CollectionChanged"),
566 // Code: Relations.CollectionChanged += handler;
567 ctor.Statements.Add (
568 new CodeAttachEventStatement (
570 PropRef ("Relations"),
571 "CollectionChanged"),
580 // protected Foo (SerializationInfo info, StreamingContext ctx)
582 // throw new NotImplementedException ();
584 private CodeConstructor CreateDataSetSerializationCtor ()
586 CodeConstructor ctor = new CodeConstructor ();
587 ctor.Attributes = MemberAttributes.Family;
588 ctor.Parameters.Add (Param (typeof (SerializationInfo), "info"));
589 ctor.Parameters.Add (Param (typeof (StreamingContext), "ctx"));
592 // // TODO: implement
593 // throw new NotImplementedException ();
594 ctor.Statements.Add (Comment ("TODO: implement"));
595 ctor.Statements.Add (Throw (New (typeof (NotImplementedException))));
601 // public override DataSet Clone()
603 // [foo] set = ([foo]) base.Clone ();
604 // set.InitializeFields ();
607 private CodeMemberMethod CreateDataSetCloneMethod (CodeTypeDeclaration dsType)
609 CodeMemberMethod m = new CodeMemberMethod ();
610 m.ReturnType = TypeRef (typeof (DataSet));
611 m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
613 // Code: [foo] set = ([foo]) base.Clone ();
614 CodeVariableReferenceExpression set = Local ("set");
615 m.Statements.Add (VarDecl (
620 MethodInvoke (Base (), "Clone"))));
621 m.Statements.Add (Eval (MethodInvoke (set, "InitializeFields")));
622 m.Statements.Add (Return (set));
627 // protected override bool ShouldSerializeTables ()
629 // return true; // it should be false
631 private CodeMemberMethod CreateDataSetShouldSerializeTables ()
633 CodeMemberMethod m = new CodeMemberMethod ();
634 m.Name = "ShouldSerializeTables";
635 m.ReturnType = TypeRef (typeof (bool));
636 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
637 // FIXME: set "false" after serialization .ctor() implementation
638 m.Statements.Add (Return (Const (true)));
643 // protected override bool ShouldSerializeRelations ()
645 // return true; // it should be false
647 private CodeMemberMethod CreateDataSetShouldSerializeRelations ()
649 CodeMemberMethod m = new CodeMemberMethod ();
650 m.Name = "ShouldSerializeRelations";
651 m.ReturnType = TypeRef (typeof (bool));
652 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
653 // FIXME: set "false" after serialization .ctor() implementation
654 m.Statements.Add (Return (Const (true)));
659 // protected override void ReadXmlSerializable()
661 // // TODO: implement
662 // throw new NotImplementedException ();
664 private CodeMemberMethod CreateDataSetReadXmlSerializable ()
666 CodeMemberMethod method = new CodeMemberMethod ();
667 method.Name = "ReadXmlSerializable";
668 method.Attributes = MemberAttributes.Family | MemberAttributes.Override;
669 method.Parameters.Add (Param (TypeRef (typeof (XmlReader)), "reader"));
671 method.Statements.Add (Comment ("TODO: implement"));
672 // Hey, how can I specify the constructor to invoke chained ctor with an empty parameter list!?
673 method.Statements.Add (Throw (New (typeof (NotImplementedException))));
677 private CodeMemberMethod CreateDataSetGetSchema ()
679 CodeMemberMethod m = new CodeMemberMethod ();
680 m.PrivateImplementationType = TypeRef (typeof (IXmlSerializable));
681 m.Name = "GetSchema";
682 m.ReturnType = TypeRef (typeof (XmlSchema));
683 m.Statements.Add (Return (MethodInvoke ("GetSchemaSerializable")));
688 private CodeMemberMethod CreateDataSetGetSchemaSerializable ()
690 CodeMemberMethod m = new CodeMemberMethod ();
691 m.Attributes = MemberAttributes.Family |
692 MemberAttributes.Override;
693 m.Name = "GetSchemaSerializable";
694 m.ReturnType = TypeRef (typeof (XmlSchema));
696 m.Statements.Add (VarDecl (typeof (StringWriter), "sw",
697 New (typeof (StringWriter))));
698 m.Statements.Add (Eval (MethodInvoke ("WriteXmlSchema", Local ("sw"))));
699 m.Statements.Add (Return (MethodInvoke (
700 TypeRefExp (typeof (XmlSchema)),
702 New (typeof (XmlTextReader),
703 New (typeof (StringReader),
704 MethodInvoke (Local ("sw"),
711 private CodeMemberMethod CreateDataSetInitializeClass ()
713 CodeMemberMethod m = new CodeMemberMethod ();
714 m.Name = "InitializeClass";
715 m.Attributes = MemberAttributes.Assembly;
717 // dataset properties
718 m.Statements.Add (Let (PropRef ("DataSetName"), Const (ds.DataSetName)));
719 m.Statements.Add (Let (PropRef ("Prefix"), Const (ds.Prefix)));
720 m.Statements.Add (Let (PropRef ("Namespace"), Const (ds.Namespace)));
721 m.Statements.Add (Let (PropRef ("Locale"), New (typeof (CultureInfo), Const (ds.Locale.Name))));
722 m.Statements.Add (Let (PropRef ("CaseSensitive"), Const (ds.CaseSensitive)));
723 m.Statements.Add (Let (PropRef ("EnforceConstraints"), Const (ds.EnforceConstraints)));
726 foreach (DataTable dt in ds.Tables) {
727 string tableFieldName = "__table" + opts.TableMemberName (dt.TableName, gen);
728 string tableTypeName = opts.TableTypeName (dt.TableName, gen);
729 m.Statements.Add (Let (FieldRef (tableFieldName), New (tableTypeName)));
730 m.Statements.Add (Eval (MethodInvoke (PropRef ("Tables"), "Add", FieldRef (tableFieldName))));
733 bool fkcExists = false;
734 bool ucExists = false;
735 // First the UniqueConstraints
736 foreach (DataTable dt in ds.Tables) {
737 string tname = "__table" + opts.TableMemberName (dt.TableName, gen);
738 foreach (Constraint c in dt.Constraints) {
739 UniqueConstraint uc = c as UniqueConstraint;
742 m.Statements.Add (VarDecl (typeof (UniqueConstraint), "uc", null));
745 CreateUniqueKeyStatements (m, uc, tname);
749 // Then the ForeignKeyConstraints
750 foreach (DataTable dt in ds.Tables) {
751 string tname = "__table" + opts.TableMemberName (dt.TableName, gen);
752 foreach (Constraint c in dt.Constraints) {
753 ForeignKeyConstraint fkc = c as ForeignKeyConstraint;
756 m.Statements.Add (VarDecl (typeof (ForeignKeyConstraint), "fkc", null));
759 string rtname = "__table" + opts.TableMemberName (fkc.RelatedTable.TableName, gen);
760 CreateForeignKeyStatements (m, fkc, tname, rtname);
764 // What if other cases? dunno. Just ignore ;-)
765 foreach (DataRelation rel in ds.Relations) {
766 string relName = opts.RelationName (rel.RelationName, gen);
767 ArrayList pcols = new ArrayList ();
768 foreach (DataColumn pcol in rel.ParentColumns)
769 pcols.Add (IndexerRef (PropRef (FieldRef ("__table" + opts.TableMemberName (rel.ParentTable.TableName, gen)), "Columns"), Const (pcol.ColumnName)));
771 ArrayList ccols = new ArrayList ();
772 foreach (DataColumn ccol in rel.ChildColumns)
773 ccols.Add (IndexerRef (PropRef (FieldRef ("__table" + opts.TableMemberName (rel.ChildTable.TableName, gen)), "Columns"), Const (ccol.ColumnName)));
776 string fieldName = "__relation" + relName;
777 m.Statements.Add (Let (FieldRef (fieldName), New (typeof (DataRelation),
778 Const (rel.RelationName),
779 NewArray (typeof (DataColumn), pcols.ToArray (typeof (CodeExpression)) as CodeExpression []),
780 NewArray (typeof (DataColumn), ccols.ToArray (typeof (CodeExpression)) as CodeExpression []),
783 m.Statements.Add (Let (PropRef (FieldRef (fieldName), "Nested"), Const (rel.Nested)));
784 m.Statements.Add (MethodInvoke (PropRef ("Relations"), "Add", FieldRef (fieldName)));
790 private void CreateUniqueKeyStatements (CodeMemberMethod m, UniqueConstraint uc, string tableField)
792 ArrayList al = new ArrayList ();
793 foreach (DataColumn col in uc.Columns)
794 al.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
796 m.Statements.Add (Let (Local ("uc"), New (
797 typeof (UniqueConstraint),
798 Const (uc.ConstraintName),
801 al.ToArray (typeof (CodeExpression)) as CodeExpression []),
802 Const (uc.IsPrimaryKey))));
803 m.Statements.Add (MethodInvoke (PropRef (FieldRef (tableField), "Constraints"), "Add", Local ("uc")));
806 private void CreateForeignKeyStatements (CodeMemberMethod m,ForeignKeyConstraint fkc, string tableField, string rtableField)
808 ArrayList pcols = new ArrayList ();
809 foreach (DataColumn col in fkc.RelatedColumns)
810 pcols.Add (IndexerRef (PropRef (FieldRef (rtableField), "Columns"), Const (col.ColumnName)));
812 ArrayList ccols = new ArrayList ();
813 foreach (DataColumn col in fkc.Columns)
814 ccols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
816 m.Statements.Add (Let (Local ("fkc"), New (
817 typeof (ForeignKeyConstraint),
818 Const (fkc.ConstraintName),
821 pcols.ToArray (typeof (CodeExpression)) as CodeExpression []),
824 ccols.ToArray (typeof (CodeExpression)) as CodeExpression []))));
826 m.Statements.Add (Let (
827 PropRef (Local ("fkc"), "AcceptRejectRule"),
828 FieldRef (TypeRefExp (typeof (AcceptRejectRule)), Enum.GetName (typeof (AcceptRejectRule), fkc.AcceptRejectRule))));
829 m.Statements.Add (Let (
830 PropRef (Local ("fkc"), "DeleteRule"),
831 FieldRef (TypeRefExp (typeof (Rule)), Enum.GetName (typeof (Rule), fkc.DeleteRule))));
832 m.Statements.Add (Let (
833 PropRef (Local ("fkc"), "UpdateRule"),
834 FieldRef (TypeRefExp (typeof (Rule)), Enum.GetName (typeof (Rule), fkc.UpdateRule))));
836 m.Statements.Add (MethodInvoke (PropRef (FieldRef (tableField), "Constraints"), "Add", Local ("fkc")));
839 private CodeMemberMethod CreateDataSetInitializeFields ()
841 CodeMemberMethod m = new CodeMemberMethod ();
842 m.Attributes = MemberAttributes.Assembly;
843 m.Name = "InitializeFields";
845 foreach (DataTable dt in ds.Tables)
846 m.Statements.Add (Eval (MethodInvoke (FieldRef ("__table" + opts.TableMemberName (dt.TableName, gen)), "InitializeFields")));
848 foreach (DataRelation rel in ds.Relations)
849 m.Statements.Add (Let (FieldRef ("__relation" + opts.RelationName (rel.RelationName, gen)), IndexerRef (PropRef ("Relations"), Const (rel.RelationName))));
854 private CodeMemberMethod CreateDataSetSchemaChanged ()
856 CodeMemberMethod m = new CodeMemberMethod ();
857 m.Name = "SchemaChanged";
858 m.Parameters.Add (Param (typeof (object), "sender"));
859 m.Parameters.Add (Param (typeof (CollectionChangeEventArgs), "e"));
862 new CodeConditionStatement (
864 PropRef (ParamRef ("e"), "Action"),
865 FieldRef (TypeRefExp (typeof (CollectionChangeAction)), "Remove")),
866 new CodeStatement [] { Eval (MethodInvoke ("InitializeFields")) },
867 new CodeStatement [] {}));
871 private void CreateDataSetTableMembers (CodeTypeDeclaration dsType, DataTable table)
873 string tableTypeName = opts.TableTypeName (table.TableName, gen);
874 string tableVarName = opts.TableMemberName (table.TableName, gen);
876 CodeMemberField privTable = new CodeMemberField ();
877 privTable.Type = TypeRef (tableTypeName);
878 privTable.Name = "__table" + tableVarName;
879 dsType.Members.Add (privTable);
881 CodeMemberProperty pubTable = new CodeMemberProperty ();
882 pubTable.Type = TypeRef (tableTypeName);
883 pubTable.Attributes = MemberAttributes.Public;
884 pubTable.Name = tableVarName;
885 pubTable.HasSet = false;
886 // Code: return __table[foo];
887 pubTable.GetStatements.Add (Return (FieldRef ("__table" + tableVarName)));
889 dsType.Members.Add (pubTable);
893 private void CreateDataSetRelationMembers (CodeTypeDeclaration dsType, DataRelation relation)
895 string relName = opts.RelationName (relation.RelationName, gen);
896 string fieldName = "__relation" + relName;
898 CodeMemberField field = new CodeMemberField ();
899 field.Type = TypeRef (typeof (DataRelation));
900 field.Name = fieldName;
901 dsType.Members.Add (field);
903 // This is not supported in MS.NET
904 CodeMemberProperty prop = new CodeMemberProperty ();
905 prop.Type = TypeRef (typeof (DataRelation));
906 prop.Attributes = MemberAttributes.Public;
909 // Code: return __relation[foo_bar];
910 prop.GetStatements.Add (Return (FieldRef (fieldName)));
911 dsType.Members.Add (prop);
918 #region DataTable class
920 private CodeTypeDeclaration GenerateDataTableType (DataTable dt)
922 CodeTypeDeclaration t = new CodeTypeDeclaration ();
923 t.Name = opts.TableTypeName (dt.TableName, gen);
924 t.BaseTypes.Add (TypeRef (typeof (DataTable)));
925 t.BaseTypes.Add (TypeRef (typeof (IEnumerable)));
927 t.Members.Add (CreateTableCtor1 (dt));
928 t.Members.Add (CreateTableCtor2 (dt));
930 t.Members.Add (CreateTableCount (dt));
931 t.Members.Add (CreateTableIndexer (dt));
933 t.Members.Add (CreateTableInitializeClass (dt));
934 t.Members.Add (CreateTableInitializeFields (dt));
936 t.Members.Add (CreateTableGetEnumerator (dt));
937 t.Members.Add (CreateTableClone (dt));
938 t.Members.Add (CreateTableCreateInstance (dt));
940 t.Members.Add (CreateTableAddRow1 (dt));
941 t.Members.Add (CreateTableAddRow2 (dt));
942 t.Members.Add (CreateTableNewRow (dt));
943 t.Members.Add (CreateTableNewRowFromBuilder (dt));
944 t.Members.Add (CreateTableRemoveRow (dt));
945 t.Members.Add (CreateTableGetRowType (dt));
947 t.Members.Add (CreateTableEventStarter (dt, "Changing"));
948 t.Members.Add (CreateTableEventStarter (dt, "Changed"));
949 t.Members.Add (CreateTableEventStarter (dt, "Deleting"));
950 t.Members.Add (CreateTableEventStarter (dt, "Deleted"));
953 t.Members.Add (CreateTableEvent (dt, "RowChanging"));
954 t.Members.Add (CreateTableEvent (dt, "RowChanged"));
955 t.Members.Add (CreateTableEvent (dt, "RowDeleting"));
956 t.Members.Add (CreateTableEvent (dt, "RowDeleted"));
959 foreach (DataColumn col in dt.Columns) {
960 t.Members.Add (CreateTableColumnField (dt, col));
961 t.Members.Add (CreateTableColumnProperty (dt, col));
968 // internal [foo]DataTable () : base ("[foo]")
970 // InitializeClass ();
972 private CodeConstructor CreateTableCtor1 (DataTable dt)
974 CodeConstructor c = new CodeConstructor ();
975 c.Attributes = MemberAttributes.Assembly;
976 c.BaseConstructorArgs.Add (Const (dt.TableName));
977 c.Statements.Add (Eval (MethodInvoke ("InitializeClass")));
978 c.Statements.Add (Eval (MethodInvoke ("InitializeFields")));
983 // internal [foo]DataTable (DataTable table) : base (table.TableName)
985 // // TODO: implement
986 // throw new NotImplementedException ();
988 private CodeConstructor CreateTableCtor2 (DataTable dt)
990 CodeConstructor c = new CodeConstructor ();
991 c.Attributes = MemberAttributes.Assembly;
992 c.Parameters.Add (Param (typeof (DataTable), "table"));
993 c.BaseConstructorArgs.Add (PropRef (ParamRef ("table"), "TableName"));
995 c.Statements.Add (Comment ("TODO: implement"));
996 c.Statements.Add (Throw (New (typeof (NotImplementedException))));
1000 private CodeMemberMethod CreateTableInitializeClass (DataTable dt)
1002 CodeMemberMethod m = new CodeMemberMethod ();
1003 m.Name = "InitializeClass";
1004 foreach (DataColumn col in dt.Columns) {
1005 m.Statements.Add (Eval (MethodInvoke (
1006 PropRef ("Columns"),
1008 New (typeof (DataColumn),
1009 Const (col.ColumnName),
1010 new CodeTypeOfExpression (col.DataType)
1016 private CodeMemberMethod CreateTableInitializeFields (DataTable dt)
1018 CodeMemberMethod m = new CodeMemberMethod ();
1019 m.Name = "InitializeFields";
1020 m.Attributes = MemberAttributes.Assembly;
1023 foreach (DataColumn col in dt.Columns) {
1024 colRef = String.Format("__column{0}", opts.TableColName (col.ColumnName, gen));
1026 m.Statements.Add (Let (FieldRef (colRef), IndexerRef (PropRef ("Columns"), Const (col.ColumnName))));
1027 if (!col.AllowDBNull)
1028 m.Statements.Add (Let (FieldRef (PropRef (colRef), "AllowDBNull"), Const (col.AllowDBNull)));
1029 if (col.DefaultValue != null && col.DefaultValue.GetType() != typeof(System.DBNull))
1030 m.Statements.Add (Let (FieldRef (PropRef (colRef), "DefaultValue"), Const (col.DefaultValue)));
1031 if (col.AutoIncrement)
1032 m.Statements.Add (Let (FieldRef (PropRef (colRef), "AutoIncrement"), Const (col.AutoIncrement)));
1033 if (col.AutoIncrementSeed != 0)
1034 m.Statements.Add (Let (FieldRef (PropRef (colRef), "AutoIncrementSeed"), Const (col.AutoIncrementSeed)));
1035 if (col.AutoIncrementStep != 1)
1036 m.Statements.Add (Let (FieldRef (PropRef (colRef), "AutoIncrementStep"), Const (col.AutoIncrementStep)));
1038 m.Statements.Add (Let (FieldRef (PropRef (colRef), "ReadOnly"), Const (col.ReadOnly)));
1043 private CodeMemberMethod CreateTableClone (DataTable dt)
1045 CodeMemberMethod m = new CodeMemberMethod ();
1047 m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
1048 m.ReturnType = TypeRef (typeof (DataTable));
1049 string typeName = opts.TableTypeName (dt.TableName, gen);
1051 VarDecl (typeName, "t", Cast (typeName, MethodInvoke (Base (), "Clone"))));
1052 m.Statements.Add (Eval (MethodInvoke (Local ("t"), "InitializeFields")));
1053 m.Statements.Add (Return (Local ("t")));
1057 private CodeMemberMethod CreateTableGetEnumerator (DataTable dt)
1059 CodeMemberMethod m = new CodeMemberMethod ();
1060 m.Name = "GetEnumerator";
1061 m.Attributes = MemberAttributes.Public;
1062 m.ReturnType = TypeRef (typeof (IEnumerator));
1063 m.Statements.Add (Return (MethodInvoke (PropRef ("Rows"), "GetEnumerator")));
1067 private CodeMemberMethod CreateTableCreateInstance (DataTable dt)
1069 CodeMemberMethod m = new CodeMemberMethod ();
1070 m.Name = "CreateInstance";
1071 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1072 m.ReturnType = TypeRef (typeof (DataTable));
1073 m.Statements.Add (Return (New (opts.TableTypeName (dt.TableName, gen))));
1077 private CodeMemberField CreateTableColumnField (DataTable dt, DataColumn col)
1079 CodeMemberField f = new CodeMemberField ();
1080 f.Name = "__column" + opts.ColumnName (col.ColumnName, gen);
1081 f.Type = TypeRef (typeof (DataColumn));
1085 private CodeMemberProperty CreateTableColumnProperty (DataTable dt, DataColumn col)
1087 string name = opts.ColumnName (col.ColumnName, gen);
1088 CodeMemberProperty p = new CodeMemberProperty ();
1089 p.Name = name + "Column";
1090 p.Attributes = MemberAttributes.Assembly;
1091 p.Type = TypeRef (typeof (DataColumn));
1093 p.GetStatements.Add (Return (FieldRef ("__column" + name)));
1097 private CodeMemberProperty CreateTableCount (DataTable dt)
1099 CodeMemberProperty p = new CodeMemberProperty ();
1101 p.Attributes = MemberAttributes.Public;
1102 p.Type = TypeRef (typeof (int));
1104 p.GetStatements.Add (Return (PropRef (PropRef ("Rows"), "Count")));
1108 private CodeMemberProperty CreateTableIndexer (DataTable dt)
1110 string rowName = opts.RowName (dt.TableName, gen);
1111 CodeMemberProperty ix = new CodeMemberProperty ();
1112 ix.Name = "Item"; // indexer
1113 ix.Attributes = MemberAttributes.Public;
1114 ix.Type = TypeRef (rowName);
1115 ix.Parameters.Add (Param (typeof (int), "i"));
1117 ix.GetStatements.Add (Return (Cast (rowName, IndexerRef (PropRef ("Rows"), ParamRef ("i")))));
1121 private CodeMemberMethod CreateTableAddRow1 (DataTable dt)
1123 CodeMemberMethod m = new CodeMemberMethod ();
1124 string rowType = opts.RowName (dt.TableName, gen);
1125 m.Name = "Add" + rowType;
1126 m.Attributes = MemberAttributes.Public;
1127 m.Parameters.Add (Param (TypeRef (rowType), "row"));
1128 m.Statements.Add (Eval (MethodInvoke (PropRef ("Rows"), "Add", ParamRef ("row"))));
1132 private CodeMemberMethod CreateTableAddRow2 (DataTable dt)
1134 CodeMemberMethod m = new CodeMemberMethod ();
1135 string rowType = opts.RowName (dt.TableName, gen);
1136 m.Name = "Add" + rowType;
1137 m.ReturnType = TypeRef (rowType);
1138 m.Attributes = MemberAttributes.Public;
1140 m.Statements.Add (VarDecl (rowType, "row", MethodInvoke ("New" + rowType)));
1142 foreach (DataColumn col in dt.Columns) {
1143 if (col.ColumnMapping == MappingType.Hidden) {
1144 foreach (DataRelation r in dt.DataSet.Relations) {
1145 if (r.ChildTable == dt) {
1147 string paramType = opts.RowName (r.ParentTable.TableName, gen);
1148 string paramName = paramType;
1149 m.Parameters.Add (Param (paramType, paramName));
1150 // CODE: SetParentRow (fooRow, DataSet.Relations ["foo_bar"]);
1151 m.Statements.Add (Eval (MethodInvoke (Local ("row"), "SetParentRow", ParamRef (paramName), IndexerRef (PropRef (PropRef ("DataSet"), "Relations"), Const (r.RelationName)))));
1158 string paramName = opts.ColumnName (col.ColumnName, gen);
1159 m.Parameters.Add (Param (col.DataType, paramName));
1160 // row ["foo"] = foo;
1161 m.Statements.Add (Let (IndexerRef (Local ("row"), Const (paramName)), ParamRef (paramName)));
1166 m.Statements.Add (MethodInvoke (PropRef ("Rows"), "Add", Local ("row")));
1167 m.Statements.Add (Return (Local ("row")));
1172 private CodeMemberMethod CreateTableNewRow (DataTable dt)
1174 CodeMemberMethod m = new CodeMemberMethod ();
1175 string rowType = opts.RowName (dt.TableName, gen);
1176 m.Name = "New" + rowType;
1177 m.ReturnType = TypeRef (rowType);
1178 m.Attributes = MemberAttributes.Public;
1179 m.Statements.Add (Return (Cast (rowType, MethodInvoke ("NewRow"))));
1183 private CodeMemberMethod CreateTableNewRowFromBuilder (DataTable dt)
1185 CodeMemberMethod m = new CodeMemberMethod ();
1186 m.Name = "NewRowFromBuilder";
1187 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1188 m.ReturnType = TypeRef (typeof (DataRow));
1189 m.Parameters.Add (Param (typeof (DataRowBuilder), "builder"));
1190 m.Statements.Add (Return (New (opts.RowName (dt.TableName, gen), ParamRef ("builder"))));
1194 private CodeMemberMethod CreateTableRemoveRow (DataTable dt)
1196 CodeMemberMethod m = new CodeMemberMethod ();
1197 string rowType = opts.RowName (dt.TableName, gen);
1198 m.Name = "Remove" + rowType;
1199 m.Attributes = MemberAttributes.Public;
1200 m.Parameters.Add (Param (TypeRef (rowType), "row"));
1201 m.Statements.Add (Eval (MethodInvoke (PropRef ("Rows"), "Remove", ParamRef ("row"))));
1205 private CodeMemberMethod CreateTableGetRowType (DataTable dt)
1207 CodeMemberMethod m = new CodeMemberMethod ();
1208 m.Name = "GetRowType";
1209 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1210 m.ReturnType = TypeRef (typeof (Type));
1211 m.Statements.Add (Return (new CodeTypeOfExpression (opts.RowName (dt.TableName, gen))));
1215 private CodeMemberMethod CreateTableEventStarter (DataTable dt, string type)
1217 CodeMemberMethod m = new CodeMemberMethod ();
1218 m.Name = "OnRow" + type;
1219 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1220 m.Parameters.Add (Param (typeof (DataRowChangeEventArgs), "e"));
1222 m.Statements.Add (Eval (MethodInvoke (
1226 string eventName = opts.TableMemberName (dt.TableName, gen) + "Row" + type;
1227 CodeStatement trueStmt = Eval (
1232 opts.EventArgsName (dt.TableName, gen),
1233 Cast (opts.RowName (dt.TableName, gen), PropRef (ParamRef ("e"), "Row")),
1234 PropRef (ParamRef ("e"), "Action"))));
1237 new CodeConditionStatement (
1238 Inequals (EventRef (eventName), Const (null)),
1239 new CodeStatement [] {trueStmt},
1240 new CodeStatement [] {}));
1245 private CodeMemberEvent CreateTableEvent (DataTable dt, string nameSuffix)
1247 CodeMemberEvent cme = new CodeMemberEvent ();
1248 cme.Attributes = MemberAttributes.Public;
1249 cme.Name = opts.TableMemberName (dt.TableName, gen) + nameSuffix;
1250 cme.Type = TypeRef (opts.TableDelegateName (dt.TableName, gen));
1260 public CodeTypeDeclaration GenerateDataRowType (DataTable dt)
1262 CodeTypeDeclaration t = new CodeTypeDeclaration ();
1263 t.Name = opts.RowName (dt.TableName, gen);
1264 t.BaseTypes.Add (TypeRef (typeof (DataRow)));
1266 t.Members.Add (CreateRowCtor (dt));
1268 t.Members.Add (CreateRowTableField (dt));
1270 foreach (DataColumn col in dt.Columns) {
1271 if (col.ColumnMapping != MappingType.Hidden) {
1272 t.Members.Add (CreateRowColumnProperty (dt, col));
1273 t.Members.Add (CreateRowColumnIsNull (dt, col));
1274 t.Members.Add (CreateRowColumnSetNull (dt, col));
1278 foreach (DataRelation rel in dt.ParentRelations)
1279 t.Members.Add (CreateRowParentRowProperty (dt, rel));
1280 foreach (DataRelation rel in dt.ChildRelations)
1281 t.Members.Add (CreateRowGetChildRows (dt, rel));
1286 private CodeConstructor CreateRowCtor (DataTable dt)
1288 CodeConstructor c = new CodeConstructor ();
1289 c.Attributes = MemberAttributes.Assembly;
1290 c.Parameters.Add (Param (typeof (DataRowBuilder), "builder"));
1291 c.BaseConstructorArgs.Add (ParamRef ("builder"));
1292 c.Statements.Add (Let (FieldRef ("table"), Cast (
1293 opts.TableTypeName (dt.TableName, gen),
1294 PropRef ("Table"))));
1298 private CodeMemberField CreateRowTableField (DataTable dt)
1300 CodeMemberField f = new CodeMemberField ();
1302 f.Type = TypeRef (opts.TableTypeName (dt.TableName, gen));
1306 private CodeMemberProperty CreateRowColumnProperty (DataTable dt, DataColumn col)
1308 CodeMemberProperty p = new CodeMemberProperty ();
1309 p.Name = opts.ColumnName (col.ColumnName, gen);
1310 p.Type = TypeRef (col.DataType);
1311 p.Attributes = MemberAttributes.Public;
1313 // This part should be better than MS code output.
1315 // object ret = this [col];
1316 // if (ret == DBNull.Value)
1317 // throw new StrongTypingException ()
1319 // return (type) ret;
1320 p.GetStatements.Add (VarDecl (typeof (object), "ret",
1323 opts.TableColName (col.ColumnName, gen) + "Column"))));
1324 p.GetStatements.Add (new CodeConditionStatement (
1327 PropRef (TypeRefExp (typeof (DBNull)), "Value")),
1328 new CodeStatement [] {
1329 Throw (New (typeof (StrongTypingException), Const ("Cannot get strong typed value since it is DB null."), Const (null))) },
1330 new CodeStatement [] {
1331 Return (Cast (col.DataType, Local ("ret"))) }));
1333 p.SetStatements.Add (Let (IndexerRef (PropRef (PropRef ("table"), opts.TableColName (col.ColumnName, gen) + "Column")), new CodePropertySetValueReferenceExpression ()));
1338 private CodeMemberMethod CreateRowColumnIsNull (DataTable dt, DataColumn col)
1340 CodeMemberMethod m = new CodeMemberMethod ();
1341 m.Name = "Is" + opts.ColumnName (col.ColumnName, gen) + "Null";
1342 m.Attributes = MemberAttributes.Public;
1343 m.ReturnType = TypeRef (typeof (bool));
1344 m.Statements.Add (Return (MethodInvoke (
1346 // table[foo].[bar]Column
1349 opts.TableColName (col.ColumnName, gen) + "Column"))));
1353 private CodeMemberMethod CreateRowColumnSetNull (DataTable dt, DataColumn col)
1355 CodeMemberMethod m = new CodeMemberMethod ();
1356 m.Name = "Set" + opts.ColumnName (col.ColumnName, gen) + "Null";
1357 m.Attributes = MemberAttributes.Public;
1358 m.Statements.Add (Let (IndexerRef (
1361 opts.TableColName (col.ColumnName, gen) + "Column")),
1362 PropRef (TypeRefExp (typeof (DBNull)), "Value")));
1367 private CodeMemberProperty CreateRowParentRowProperty (DataTable dt, DataRelation rel)
1369 CodeMemberProperty p = new CodeMemberProperty ();
1370 p.Name = opts.TableMemberName (rel.ParentTable.TableName, gen) + "Row" +
1371 (rel.ParentTable.TableName == rel.ChildTable.TableName ? "Parent" : String.Empty);
1372 p.Attributes = MemberAttributes.Public;
1373 p.Type = TypeRef (opts.RowName (rel.ParentTable.TableName, gen));
1374 p.GetStatements.Add (Return (Cast (p.Type, MethodInvoke (
1382 Const (rel.RelationName))))));
1383 p.SetStatements.Add (Eval (MethodInvoke (
1385 new CodePropertySetValueReferenceExpression (),
1392 Const (rel.RelationName)))));
1397 private CodeMemberMethod CreateRowGetChildRows (DataTable dt, DataRelation rel)
1399 CodeMemberMethod m = new CodeMemberMethod ();
1400 m.Name = "Get" + opts.TableMemberName (rel.ChildTable.TableName, gen) + "Rows";
1401 m.Attributes = MemberAttributes.Public;
1402 m.ReturnType = new CodeTypeReference (opts.RowName (rel.ChildTable.TableName, gen), 1);
1403 m.Statements.Add (Return (Cast (m.ReturnType, MethodInvoke (
1411 Const (rel.RelationName))))));
1421 // public class [foo]ChangeEventArgs : EventArgs
1423 // private [foo]Row row;
1424 // private DataRowAction action;
1429 private CodeTypeDeclaration GenerateEventType (DataTable dt)
1431 CodeTypeDeclaration t = new CodeTypeDeclaration ();
1432 t.Name = opts.EventArgsName (dt.TableName, gen);
1433 t.BaseTypes.Add (TypeRef (typeof (EventArgs)));
1434 t.Attributes = MemberAttributes.Public;
1437 new CodeMemberField (
1438 TypeRef (opts.RowName (dt.TableName, gen)),
1441 new CodeMemberField (
1442 TypeRef (typeof (DataRowAction)), "action"));
1443 t.Members.Add (CreateEventCtor (dt));
1445 t.Members.Add (CreateEventRow (dt));
1447 t.Members.Add (CreateEventAction (dt));
1453 // public [foo]RowChangeEventArgs ([foo]Row r, DataRowAction a)
1458 private CodeConstructor CreateEventCtor (DataTable dt)
1460 CodeConstructor c = new CodeConstructor ();
1461 c.Attributes = MemberAttributes.Public;
1462 c.Parameters.Add (Param (TypeRef (opts.RowName (dt.TableName, gen)), "r"));
1463 c.Parameters.Add (Param (TypeRef (typeof (DataRowAction)), "a"));
1464 c.Statements.Add (Let (FieldRef ("row"), ParamRef ("r")));
1465 c.Statements.Add (Let (FieldRef ("action"), ParamRef ("a")));
1471 // public [foo]Row Row {
1472 // get { return row; }
1474 private CodeMemberProperty CreateEventRow (DataTable dt)
1476 CodeMemberProperty p = new CodeMemberProperty ();
1478 p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
1479 p.Type = TypeRef (opts.RowName (dt.TableName, gen));
1481 p.GetStatements.Add (Return (FieldRef ("row")));
1486 // public DataRowAction Action {
1487 // get { return action; }
1489 private CodeMemberProperty CreateEventAction (DataTable dt)
1491 CodeMemberProperty p = new CodeMemberProperty ();
1493 p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
1494 p.Type = TypeRef (typeof (DataRowAction));
1496 p.GetStatements.Add (Return (FieldRef ("action")));
1506 /* =========================================================
1509 MonoDataSetGenerator API notes
1513 CreateDataSetClasses (
1517 GeneratorOptions options)
1521 *** Code naming method delegate
1523 public delegate string CodeNamingMethod (string sourceName);
1525 It is used in CodeGeneratorOptions (describled immediately below).
1529 *** Generator Options
1531 public bool MakeClassesInsideDataSet
1532 indicates whether classes and delegates other than DataSet
1533 itself are "contained" in the DataSet class or not.
1535 public CodeNamingMethod CreateDataSetName;
1536 public CodeNamingMethod CreateTableTypeName;
1537 public CodeNamingMethod CreateTableMemberName;
1538 public CodeNamingMethod CreateColumnName;
1539 public CodeNamingMethod CreateRowName;
1540 public CodeNamingMethod CreateRelationName;
1541 public CodeNamingMethod CreateTableDelegateName;
1542 public CodeNamingMethod CreateEventArgsName;
1543 Custom methods each of that returns type or member name.
1545 By default, they are set as to useTypedDataSetGenerator.
1546 CreateIdName() with modifications listed as below:
1549 TableTypeName: "DataTable" suffix
1550 TableMemberName: as is
1552 RowName: "Row" suffix
1553 RelationName: (TBD; maybe had better have another delegate type)
1554 DelegateName: "RowChangedEventHandler" suffix
1555 EventArgsName: "RowChangedEventArgs" suffix
1557 ** Auto Generated classes
1559 1. Custom DataSet class
1561 class name = dataset name, encoded by options.CreateDataSetName().
1565 public default .ctor()
1567 set custom delegate on Tables.CollectionChanged
1568 set custom delegate on Relations.CollectionChanged
1570 runtime serialization .ctor()
1575 data tables: [foo]DataTable foo { return this.table[foo]; }
1578 init variables on new dataset.
1580 *** protected members
1582 ShouldSerializeTables()
1583 returns false, while default DataSet returns true.
1584 ShouldSerializeRelations()
1585 returns false, while default DataSet returns true.
1587 ReadXmlSerializable() ... similar to runtime serialization
1590 GetSchemaSerializable()
1591 Write its schema to temporary MemoryStream
1592 Read XML schema from the stream
1594 *** internal members
1597 set member fields (tables, relations)
1598 call members' "init variables"
1601 set DataSetName, Prefix, Namespace, Locale, CaseSensitive, EnforceConstraints
1605 create FKC: new FKC([rel], new DataColumn [] {table[foo].[keyColumnName]Column}, new DataColumn [] {table[child].[childColName]Column}
1606 fill Rule properties.
1607 allocate relation[rel] and fill Nested, then Relations.Add()
1611 data tables: [foo]DataTable table[foo];
1613 data relations: DataRelation relation[rel];
1615 ShouldSerialize[foo]
1619 2. Custom DataTable classes for each DataTable
1621 This class is created under the dataset.
1623 *** internal members
1625 .ctor() : base("[foo]")
1631 DataColumn [bar]Column { return column[bar]; }
1634 fill each column fields
1638 int Count { rowcount }
1640 this [int index] { row [i]; }
1642 event [foo]RowChangedEventHandler [foo]RowChanged
1643 event [foo]RowChangedEventHandler [foo]RowChanging
1644 event [foo]RowChangedEventHandler [foo]RowDeleted
1645 event [foo]RowChangedEventHandler [foo]RowDeleting
1647 void Add[foo]Row ([foo]Row row) { Rows.Add (row); }
1649 [foo]Row Add[foo]Row ([columnType] [columnName])
1650 create new [foo]row.
1654 // non-relation-children are just created as column type
1655 // relation-children are typeof fooRow[]
1657 GetEnumerator() { Rows.GetEnumerator (); }
1659 override DataTable Clone()
1662 [foo]Row New[foo]Row()
1664 void Remove[foo]Row([foo]Row)
1666 //for each ChildRelations
1667 [bar]Row [] Get[foo_bar]Rows ()
1669 *** protected members
1671 override DataTable CreateInstance() { return new }
1673 override DataRow NewRowFromBuilder(DataRowBuilder)
1675 override Type GetRowType()
1677 override void OnRowChanged(DataRowChangedEventArgs)
1679 check this event [foo]RowChanged.
1681 override void OnRowChanging(DataRowChangedEventArgs)
1682 override void OnRowDeleted(DataRowChangedEventArgs)
1683 override void OnRowDeleting(DataRowChangedEventArgs)
1690 column[bar] = new DataColumn (...);
1694 DataColumn [bar]Column
1696 3. Custom DataRow classses
1703 get { try { } catch { throw StrongTypingException(); }
1704 set { this [[foo]Table.[bar]Column] = value; }
1707 IsNull ([foo]Table.[bar]Column);
1709 void Set[bar]Null ()
1711 if the table is parent of some relations
1713 public [child]Row [] Get[child]Rows()
1715 *** internal members
1717 .ctor(DataRowBuilder) : base.()
1722 [foo]DataTable table[foo]
1725 4. Custom DataRowChangeEvent classes
1730 DataRowAction eventAction
1734 .ctor([foo]Row row, DataRowAction action)
1738 DataRowAction Action
1742 5. public Table RowChangedEventHandler delegates
1744 [foo]RowChangedEventHandler(object, [foo]RowChangedEvent e)
1747 ======================================================== */