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 private CodeBinaryOperatorExpression EqualsValue (CodeExpression exp1, CodeExpression exp2)
435 return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.ValueEquality, exp2);
438 // note that this is "Identity" equality comparison
439 private CodeBinaryOperatorExpression Equals (CodeExpression exp1, CodeExpression exp2)
441 return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.IdentityEquality, exp2);
444 private CodeBinaryOperatorExpression Inequals (CodeExpression exp1, CodeExpression exp2)
446 return new CodeBinaryOperatorExpression (exp1, CodeBinaryOperatorType.IdentityInequality, exp2);
449 private CodeTypeReferenceExpression TypeRefExp (Type t)
451 return new CodeTypeReferenceExpression (t);
455 private CodeExpressionStatement Eval (CodeExpression exp)
457 return new CodeExpressionStatement (exp);
460 private CodeAssignStatement Let (CodeExpression exp, CodeExpression value)
462 return new CodeAssignStatement (exp, value);
465 private CodeMethodReturnStatement Return (CodeExpression exp)
467 return new CodeMethodReturnStatement (exp);
470 private CodeVariableDeclarationStatement VarDecl (Type t,
471 string name, CodeExpression init)
473 return new CodeVariableDeclarationStatement (t, name, init);
476 private CodeVariableDeclarationStatement VarDecl (string t,
477 string name, CodeExpression init)
479 return new CodeVariableDeclarationStatement (t, name, init);
482 private CodeCommentStatement Comment (string comment)
484 return new CodeCommentStatement (comment);
487 private CodeThrowExceptionStatement Throw (CodeExpression exp)
489 return new CodeThrowExceptionStatement (exp);
492 #region DataSet class
494 private CodeTypeDeclaration GenerateDataSetType ()
497 dsType = new CodeTypeDeclaration (opts.DataSetName (ds.DataSetName, gen));
498 dsType.BaseTypes.Add (TypeRef (typeof (DataSet)));
499 dsType.BaseTypes.Add (TypeRef (typeof (IXmlSerializable)));
502 dsType.Members.Add (CreateDataSetDefaultCtor ());
503 // runtime serialization .ctor()
504 dsType.Members.Add (CreateDataSetSerializationCtor ());
507 dsType.Members.Add (CreateDataSetCloneMethod (dsType));
509 // FIXME: I keep these methods out of the generated source right now.
510 // It should be added after runtime serialization was implemented.
512 // ShouldSerializeTables()
513 dsType.Members.Add (CreateDataSetShouldSerializeTables ());
515 // ShouldSerializeRelations()
516 dsType.Members.Add (CreateDataSetShouldSerializeRelations ());
518 // ReadXmlSerializable()
519 dsType.Members.Add (CreateDataSetReadXmlSerializable ());
522 // GetSchemaSerializable()
523 dsType.Members.Add (CreateDataSetGetSchemaSerializable ());
525 dsType.Members.Add (CreateDataSetGetSchema ());
526 dsType.Members.Add (CreateDataSetInitializeClass ());
527 dsType.Members.Add (CreateDataSetInitializeFields ());
528 dsType.Members.Add (CreateDataSetSchemaChanged ());
530 // table class and members
531 foreach (DataTable table in ds.Tables)
532 CreateDataSetTableMembers (dsType, table);
533 // relation class and members
534 foreach (DataRelation rel in ds.Relations)
535 CreateDataSetRelationMembers (dsType, rel);
543 // InitializeClass();
544 // CollectionChangeEventHandler handler = new CollectionChangeEventHandler (SchemaChanged);
545 // Tables.CollectionChanged += handler;
546 // Relations.CollectionChanged += handler;
548 private CodeConstructor CreateDataSetDefaultCtor ()
550 CodeConstructor ctor = new CodeConstructor ();
551 ctor.Attributes = MemberAttributes.Public;
552 // Code: InitializeClass().
553 ctor.Statements.Add (Eval (MethodInvoke ("InitializeClass")));
555 // Code: CollectionChangedEventHandler handler = new CollectionChangeEventHandler (SchemeChanged);
556 CodeVariableDeclarationStatement stmt2 =
558 typeof (CollectionChangeEventHandler),
561 typeof (CollectionChangeEventHandler),
562 new CodeDelegateCreateExpression (
563 new CodeTypeReference (typeof (CollectionChangeEventHandler)),
564 new CodeThisReferenceExpression (),
567 ctor.Statements.Add (stmt2);
569 // Code: Tables.CollectionChanged += handler;
570 ctor.Statements.Add (
571 new CodeAttachEventStatement (
574 "CollectionChanged"),
577 // Code: Relations.CollectionChanged += handler;
578 ctor.Statements.Add (
579 new CodeAttachEventStatement (
581 PropRef ("Relations"),
582 "CollectionChanged"),
591 // protected Foo (SerializationInfo info, StreamingContext ctx)
593 // throw new NotImplementedException ();
595 private CodeConstructor CreateDataSetSerializationCtor ()
597 CodeConstructor ctor = new CodeConstructor ();
598 ctor.Attributes = MemberAttributes.Family;
599 ctor.Parameters.Add (Param (typeof (SerializationInfo), "info"));
600 ctor.Parameters.Add (Param (typeof (StreamingContext), "ctx"));
603 // // TODO: implement
604 // throw new NotImplementedException ();
605 ctor.Statements.Add (Comment ("TODO: implement"));
606 ctor.Statements.Add (Throw (New (typeof (NotImplementedException))));
612 // public override DataSet Clone()
614 // [foo] set = ([foo]) base.Clone ();
615 // set.InitializeFields ();
618 private CodeMemberMethod CreateDataSetCloneMethod (CodeTypeDeclaration dsType)
620 CodeMemberMethod m = new CodeMemberMethod ();
621 m.ReturnType = TypeRef (typeof (DataSet));
622 m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
624 // Code: [foo] set = ([foo]) base.Clone ();
625 CodeVariableReferenceExpression set = Local ("set");
626 m.Statements.Add (VarDecl (
631 MethodInvoke (Base (), "Clone"))));
632 m.Statements.Add (Eval (MethodInvoke (set, "InitializeFields")));
633 m.Statements.Add (Return (set));
638 // protected override bool ShouldSerializeTables ()
640 // return true; // it should be false
643 private CodeMemberMethod CreateDataSetShouldSerializeTables ()
645 CodeMemberMethod m = new CodeMemberMethod ();
646 m.Name = "ShouldSerializeTables";
647 m.ReturnType = TypeRef (typeof (bool));
648 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
649 // FIXME: set "false" after serialization .ctor() implementation
650 m.Statements.Add (Return (Const (true)));
655 // protected override bool ShouldSerializeRelations ()
657 // return true; // it should be false
661 private CodeMemberMethod CreateDataSetShouldSerializeRelations ()
663 CodeMemberMethod m = new CodeMemberMethod ();
664 m.Name = "ShouldSerializeRelations";
665 m.ReturnType = TypeRef (typeof (bool));
666 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
667 // FIXME: set "false" after serialization .ctor() implementation
668 m.Statements.Add (Return (Const (true)));
674 // protected override void ReadXmlSerializable()
676 // // TODO: implement
677 // throw new NotImplementedException ();
680 private CodeMemberMethod CreateDataSetReadXmlSerializable ()
682 CodeMemberMethod method = new CodeMemberMethod ();
683 method.Name = "ReadXmlSerializable";
684 method.Attributes = MemberAttributes.Family | MemberAttributes.Override;
685 method.Parameters.Add (Param (TypeRef (typeof (XmlReader)), "reader"));
687 method.Statements.Add (Comment ("TODO: implement"));
688 // Hey, how can I specify the constructor to invoke chained ctor with an empty parameter list!?
689 method.Statements.Add (Throw (New (typeof (NotImplementedException))));
694 private CodeMemberMethod CreateDataSetGetSchema ()
696 CodeMemberMethod m = new CodeMemberMethod ();
697 m.PrivateImplementationType = TypeRef (typeof (IXmlSerializable));
698 m.Name = "GetSchema";
699 m.ReturnType = TypeRef (typeof (XmlSchema));
700 m.Statements.Add (Return (MethodInvoke ("GetSchemaSerializable")));
705 private CodeMemberMethod CreateDataSetGetSchemaSerializable ()
707 CodeMemberMethod m = new CodeMemberMethod ();
708 m.Attributes = MemberAttributes.Family |
709 MemberAttributes.Override;
710 m.Name = "GetSchemaSerializable";
711 m.ReturnType = TypeRef (typeof (XmlSchema));
713 m.Statements.Add (VarDecl (typeof (StringWriter), "sw",
714 New (typeof (StringWriter))));
715 m.Statements.Add (Eval (MethodInvoke ("WriteXmlSchema", Local ("sw"))));
716 m.Statements.Add (Return (MethodInvoke (
717 TypeRefExp (typeof (XmlSchema)),
719 New (typeof (XmlTextReader),
720 New (typeof (StringReader),
721 MethodInvoke (Local ("sw"),
728 private CodeMemberMethod CreateDataSetInitializeClass ()
730 CodeMemberMethod m = new CodeMemberMethod ();
731 m.Name = "InitializeClass";
732 m.Attributes = MemberAttributes.Assembly;
734 // dataset properties
735 m.Statements.Add (Let (PropRef ("DataSetName"), Const (ds.DataSetName)));
736 m.Statements.Add (Let (PropRef ("Prefix"), Const (ds.Prefix)));
737 m.Statements.Add (Let (PropRef ("Namespace"), Const (ds.Namespace)));
738 m.Statements.Add (Let (PropRef ("Locale"), New (typeof (CultureInfo), Const (ds.Locale.Name))));
739 m.Statements.Add (Let (PropRef ("CaseSensitive"), Const (ds.CaseSensitive)));
740 m.Statements.Add (Let (PropRef ("EnforceConstraints"), Const (ds.EnforceConstraints)));
743 foreach (DataTable dt in ds.Tables) {
744 string tableFieldName = "__table" + opts.TableMemberName (dt.TableName, gen);
745 string tableTypeName = opts.TableTypeName (dt.TableName, gen);
746 m.Statements.Add (Let (FieldRef (tableFieldName), New (tableTypeName)));
747 m.Statements.Add (Eval (MethodInvoke (PropRef ("Tables"), "Add", FieldRef (tableFieldName))));
750 bool fkcExists = false;
751 bool ucExists = false;
752 // First the UniqueConstraints
753 foreach (DataTable dt in ds.Tables) {
754 string tname = "__table" + opts.TableMemberName (dt.TableName, gen);
755 foreach (Constraint c in dt.Constraints) {
756 UniqueConstraint uc = c as UniqueConstraint;
759 m.Statements.Add (VarDecl (typeof (UniqueConstraint), "uc", null));
762 CreateUniqueKeyStatements (m, uc, tname);
766 // Then the ForeignKeyConstraints
767 foreach (DataTable dt in ds.Tables) {
768 string tname = "__table" + opts.TableMemberName (dt.TableName, gen);
769 foreach (Constraint c in dt.Constraints) {
770 ForeignKeyConstraint fkc = c as ForeignKeyConstraint;
773 m.Statements.Add (VarDecl (typeof (ForeignKeyConstraint), "fkc", null));
776 string rtname = "__table" + opts.TableMemberName (fkc.RelatedTable.TableName, gen);
777 CreateForeignKeyStatements (m, fkc, tname, rtname);
781 // What if other cases? dunno. Just ignore ;-)
782 foreach (DataRelation rel in ds.Relations) {
783 string relName = opts.RelationName (rel.RelationName, gen);
784 ArrayList pcols = new ArrayList ();
785 foreach (DataColumn pcol in rel.ParentColumns)
786 pcols.Add (IndexerRef (PropRef (FieldRef ("__table" + opts.TableMemberName (rel.ParentTable.TableName, gen)), "Columns"), Const (pcol.ColumnName)));
788 ArrayList ccols = new ArrayList ();
789 foreach (DataColumn ccol in rel.ChildColumns)
790 ccols.Add (IndexerRef (PropRef (FieldRef ("__table" + opts.TableMemberName (rel.ChildTable.TableName, gen)), "Columns"), Const (ccol.ColumnName)));
793 string fieldName = "__relation" + relName;
794 m.Statements.Add (Let (FieldRef (fieldName), New (typeof (DataRelation),
795 Const (rel.RelationName),
796 NewArray (typeof (DataColumn), pcols.ToArray (typeof (CodeExpression)) as CodeExpression []),
797 NewArray (typeof (DataColumn), ccols.ToArray (typeof (CodeExpression)) as CodeExpression []),
800 m.Statements.Add (Let (PropRef (FieldRef (fieldName), "Nested"), Const (rel.Nested)));
801 m.Statements.Add (MethodInvoke (PropRef ("Relations"), "Add", FieldRef (fieldName)));
807 private void CreateUniqueKeyStatements (CodeMemberMethod m, UniqueConstraint uc, string tableField)
809 ArrayList al = new ArrayList ();
810 foreach (DataColumn col in uc.Columns)
811 al.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
813 m.Statements.Add (Let (Local ("uc"), New (
814 typeof (UniqueConstraint),
815 Const (uc.ConstraintName),
818 al.ToArray (typeof (CodeExpression)) as CodeExpression []),
819 Const (uc.IsPrimaryKey))));
820 m.Statements.Add (MethodInvoke (PropRef (FieldRef (tableField), "Constraints"), "Add", Local ("uc")));
823 private void CreateForeignKeyStatements (CodeMemberMethod m,ForeignKeyConstraint fkc, string tableField, string rtableField)
825 ArrayList pcols = new ArrayList ();
826 foreach (DataColumn col in fkc.RelatedColumns)
827 pcols.Add (IndexerRef (PropRef (FieldRef (rtableField), "Columns"), Const (col.ColumnName)));
829 ArrayList ccols = new ArrayList ();
830 foreach (DataColumn col in fkc.Columns)
831 ccols.Add (IndexerRef (PropRef (FieldRef (tableField), "Columns"), Const (col.ColumnName)));
833 m.Statements.Add (Let (Local ("fkc"), New (
834 typeof (ForeignKeyConstraint),
835 Const (fkc.ConstraintName),
838 pcols.ToArray (typeof (CodeExpression)) as CodeExpression []),
841 ccols.ToArray (typeof (CodeExpression)) as CodeExpression []))));
843 m.Statements.Add (Let (
844 PropRef (Local ("fkc"), "AcceptRejectRule"),
845 FieldRef (TypeRefExp (typeof (AcceptRejectRule)), Enum.GetName (typeof (AcceptRejectRule), fkc.AcceptRejectRule))));
846 m.Statements.Add (Let (
847 PropRef (Local ("fkc"), "DeleteRule"),
848 FieldRef (TypeRefExp (typeof (Rule)), Enum.GetName (typeof (Rule), fkc.DeleteRule))));
849 m.Statements.Add (Let (
850 PropRef (Local ("fkc"), "UpdateRule"),
851 FieldRef (TypeRefExp (typeof (Rule)), Enum.GetName (typeof (Rule), fkc.UpdateRule))));
853 m.Statements.Add (MethodInvoke (PropRef (FieldRef (tableField), "Constraints"), "Add", Local ("fkc")));
856 private CodeMemberMethod CreateDataSetInitializeFields ()
858 CodeMemberMethod m = new CodeMemberMethod ();
859 m.Attributes = MemberAttributes.Assembly;
860 m.Name = "InitializeFields";
862 foreach (DataTable dt in ds.Tables)
863 m.Statements.Add (Eval (MethodInvoke (FieldRef ("__table" + opts.TableMemberName (dt.TableName, gen)), "InitializeFields")));
865 foreach (DataRelation rel in ds.Relations)
866 m.Statements.Add (Let (FieldRef ("__relation" + opts.RelationName (rel.RelationName, gen)), IndexerRef (PropRef ("Relations"), Const (rel.RelationName))));
871 private CodeMemberMethod CreateDataSetSchemaChanged ()
873 CodeMemberMethod m = new CodeMemberMethod ();
874 m.Name = "SchemaChanged";
875 m.Parameters.Add (Param (typeof (object), "sender"));
876 m.Parameters.Add (Param (typeof (CollectionChangeEventArgs), "e"));
879 new CodeConditionStatement (
881 PropRef (ParamRef ("e"), "Action"),
882 FieldRef (TypeRefExp (typeof (CollectionChangeAction)), "Remove")),
883 new CodeStatement [] { Eval (MethodInvoke ("InitializeFields")) },
884 new CodeStatement [] {}));
888 private void CreateDataSetTableMembers (CodeTypeDeclaration dsType, DataTable table)
890 string tableTypeName = opts.TableTypeName (table.TableName, gen);
891 string tableVarName = opts.TableMemberName (table.TableName, gen);
893 CodeMemberField privTable = new CodeMemberField ();
894 privTable.Type = TypeRef (tableTypeName);
895 privTable.Name = "__table" + tableVarName;
896 dsType.Members.Add (privTable);
898 CodeMemberProperty pubTable = new CodeMemberProperty ();
899 pubTable.Type = TypeRef (tableTypeName);
900 pubTable.Attributes = MemberAttributes.Public;
901 pubTable.Name = tableVarName;
902 pubTable.HasSet = false;
903 // Code: return __table[foo];
904 pubTable.GetStatements.Add (Return (FieldRef ("__table" + tableVarName)));
906 dsType.Members.Add (pubTable);
910 private void CreateDataSetRelationMembers (CodeTypeDeclaration dsType, DataRelation relation)
912 string relName = opts.RelationName (relation.RelationName, gen);
913 string fieldName = "__relation" + relName;
915 CodeMemberField field = new CodeMemberField ();
916 field.Type = TypeRef (typeof (DataRelation));
917 field.Name = fieldName;
918 dsType.Members.Add (field);
920 // This is not supported in MS.NET
921 CodeMemberProperty prop = new CodeMemberProperty ();
922 prop.Type = TypeRef (typeof (DataRelation));
923 prop.Attributes = MemberAttributes.Public;
926 // Code: return __relation[foo_bar];
927 prop.GetStatements.Add (Return (FieldRef (fieldName)));
928 dsType.Members.Add (prop);
935 #region DataTable class
937 private CodeTypeDeclaration GenerateDataTableType (DataTable dt)
939 CodeTypeDeclaration t = new CodeTypeDeclaration ();
940 t.Name = opts.TableTypeName (dt.TableName, gen);
941 t.BaseTypes.Add (TypeRef (typeof (DataTable)));
942 t.BaseTypes.Add (TypeRef (typeof (IEnumerable)));
944 t.Members.Add (CreateTableCtor1 (dt));
945 t.Members.Add (CreateTableCtor2 (dt));
947 t.Members.Add (CreateTableCount (dt));
948 t.Members.Add (CreateTableIndexer (dt));
950 t.Members.Add (CreateTableInitializeClass (dt));
951 t.Members.Add (CreateTableInitializeFields (dt));
953 t.Members.Add (CreateTableGetEnumerator (dt));
954 t.Members.Add (CreateTableClone (dt));
955 t.Members.Add (CreateTableCreateInstance (dt));
957 t.Members.Add (CreateTableAddRow1 (dt));
958 t.Members.Add (CreateTableAddRow2 (dt));
959 t.Members.Add (CreateTableNewRow (dt));
960 t.Members.Add (CreateTableNewRowFromBuilder (dt));
961 t.Members.Add (CreateTableRemoveRow (dt));
962 t.Members.Add (CreateTableGetRowType (dt));
964 t.Members.Add (CreateTableEventStarter (dt, "Changing"));
965 t.Members.Add (CreateTableEventStarter (dt, "Changed"));
966 t.Members.Add (CreateTableEventStarter (dt, "Deleting"));
967 t.Members.Add (CreateTableEventStarter (dt, "Deleted"));
970 t.Members.Add (CreateTableEvent (dt, "RowChanging"));
971 t.Members.Add (CreateTableEvent (dt, "RowChanged"));
972 t.Members.Add (CreateTableEvent (dt, "RowDeleting"));
973 t.Members.Add (CreateTableEvent (dt, "RowDeleted"));
976 foreach (DataColumn col in dt.Columns) {
977 t.Members.Add (CreateTableColumnField (dt, col));
978 t.Members.Add (CreateTableColumnProperty (dt, col));
985 // internal [foo]DataTable () : base ("[foo]")
987 // InitializeClass ();
989 private CodeConstructor CreateTableCtor1 (DataTable dt)
991 CodeConstructor c = new CodeConstructor ();
992 c.Attributes = MemberAttributes.Assembly;
993 c.BaseConstructorArgs.Add (Const (dt.TableName));
994 c.Statements.Add (Eval (MethodInvoke ("InitializeClass")));
995 c.Statements.Add (Eval (MethodInvoke ("InitializeFields")));
1000 // internal [foo]DataTable (DataTable table) : base (table.TableName)
1002 // // TODO: implement
1003 // throw new NotImplementedException ();
1005 private CodeConstructor CreateTableCtor2 (DataTable dt)
1007 CodeConstructor c = new CodeConstructor ();
1008 c.Attributes = MemberAttributes.Assembly;
1009 c.Parameters.Add (Param (typeof (DataTable), GetRowTableFieldName (dt)));
1010 c.BaseConstructorArgs.Add (PropRef (ParamRef (GetRowTableFieldName (dt)), "TableName"));
1012 c.Statements.Add (Comment ("TODO: implement"));
1013 c.Statements.Add (Throw (New (typeof (NotImplementedException))));
1017 private CodeMemberMethod CreateTableInitializeClass (DataTable dt)
1019 CodeMemberMethod m = new CodeMemberMethod ();
1020 m.Name = "InitializeClass";
1021 foreach (DataColumn col in dt.Columns) {
1022 m.Statements.Add (Eval (MethodInvoke (
1023 PropRef ("Columns"),
1025 New (typeof (DataColumn),
1026 Const (col.ColumnName),
1027 new CodeTypeOfExpression (col.DataType)
1033 private CodeMemberMethod CreateTableInitializeFields (DataTable dt)
1035 CodeMemberMethod m = new CodeMemberMethod ();
1036 m.Name = "InitializeFields";
1037 m.Attributes = MemberAttributes.Assembly;
1040 foreach (DataColumn col in dt.Columns) {
1041 colRef = String.Format("__column{0}", opts.TableColName (col.ColumnName, gen));
1043 m.Statements.Add (Let (FieldRef (colRef), IndexerRef (PropRef ("Columns"), Const (col.ColumnName))));
1044 if (!col.AllowDBNull)
1045 m.Statements.Add (Let (FieldRef (PropRef (colRef), "AllowDBNull"), Const (col.AllowDBNull)));
1046 if (col.DefaultValue != null && col.DefaultValue.GetType() != typeof(System.DBNull))
1047 m.Statements.Add (Let (FieldRef (PropRef (colRef), "DefaultValue"), Const (col.DefaultValue)));
1048 if (col.AutoIncrement)
1049 m.Statements.Add (Let (FieldRef (PropRef (colRef), "AutoIncrement"), Const (col.AutoIncrement)));
1050 if (col.AutoIncrementSeed != 0)
1051 m.Statements.Add (Let (FieldRef (PropRef (colRef), "AutoIncrementSeed"), Const (col.AutoIncrementSeed)));
1052 if (col.AutoIncrementStep != 1)
1053 m.Statements.Add (Let (FieldRef (PropRef (colRef), "AutoIncrementStep"), Const (col.AutoIncrementStep)));
1055 m.Statements.Add (Let (FieldRef (PropRef (colRef), "ReadOnly"), Const (col.ReadOnly)));
1060 private CodeMemberMethod CreateTableClone (DataTable dt)
1062 CodeMemberMethod m = new CodeMemberMethod ();
1064 m.Attributes = MemberAttributes.Public | MemberAttributes.Override;
1065 m.ReturnType = TypeRef (typeof (DataTable));
1066 string typeName = opts.TableTypeName (dt.TableName, gen);
1068 VarDecl (typeName, "t", Cast (typeName, MethodInvoke (Base (), "Clone"))));
1069 m.Statements.Add (Eval (MethodInvoke (Local ("t"), "InitializeFields")));
1070 m.Statements.Add (Return (Local ("t")));
1074 private CodeMemberMethod CreateTableGetEnumerator (DataTable dt)
1076 CodeMemberMethod m = new CodeMemberMethod ();
1077 m.Name = "GetEnumerator";
1078 m.Attributes = MemberAttributes.Public;
1079 m.ReturnType = TypeRef (typeof (IEnumerator));
1080 m.Statements.Add (Return (MethodInvoke (PropRef ("Rows"), "GetEnumerator")));
1081 m.ImplementationTypes.Add (TypeRef (typeof (IEnumerable)));
1085 private CodeMemberMethod CreateTableCreateInstance (DataTable dt)
1087 CodeMemberMethod m = new CodeMemberMethod ();
1088 m.Name = "CreateInstance";
1089 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1090 m.ReturnType = TypeRef (typeof (DataTable));
1091 m.Statements.Add (Return (New (opts.TableTypeName (dt.TableName, gen))));
1095 private CodeMemberField CreateTableColumnField (DataTable dt, DataColumn col)
1097 CodeMemberField f = new CodeMemberField ();
1098 f.Name = "__column" + opts.ColumnName (col.ColumnName, gen);
1099 f.Type = TypeRef (typeof (DataColumn));
1103 private CodeMemberProperty CreateTableColumnProperty (DataTable dt, DataColumn col)
1105 string name = opts.ColumnName (col.ColumnName, gen);
1106 CodeMemberProperty p = new CodeMemberProperty ();
1107 p.Name = name + "Column";
1108 p.Attributes = MemberAttributes.Assembly;
1109 p.Type = TypeRef (typeof (DataColumn));
1111 p.GetStatements.Add (Return (FieldRef ("__column" + name)));
1115 private CodeMemberProperty CreateTableCount (DataTable dt)
1117 CodeMemberProperty p = new CodeMemberProperty ();
1119 p.Attributes = MemberAttributes.Public;
1120 p.Type = TypeRef (typeof (int));
1122 p.GetStatements.Add (Return (PropRef (PropRef ("Rows"), "Count")));
1126 private CodeMemberProperty CreateTableIndexer (DataTable dt)
1128 string rowName = opts.RowName (dt.TableName, gen);
1129 CodeMemberProperty ix = new CodeMemberProperty ();
1130 ix.Name = "Item"; // indexer
1131 ix.Attributes = MemberAttributes.Public;
1132 ix.Type = TypeRef (rowName);
1133 ix.Parameters.Add (Param (typeof (int), "i"));
1135 ix.GetStatements.Add (Return (Cast (rowName, IndexerRef (PropRef ("Rows"), ParamRef ("i")))));
1139 private CodeMemberMethod CreateTableAddRow1 (DataTable dt)
1141 CodeMemberMethod m = new CodeMemberMethod ();
1142 string rowType = opts.RowName (dt.TableName, gen);
1143 m.Name = "Add" + rowType;
1144 m.Attributes = MemberAttributes.Public;
1145 m.Parameters.Add (Param (TypeRef (rowType), "row"));
1146 m.Statements.Add (Eval (MethodInvoke (PropRef ("Rows"), "Add", ParamRef ("row"))));
1150 private CodeMemberMethod CreateTableAddRow2 (DataTable dt)
1152 CodeMemberMethod m = new CodeMemberMethod ();
1153 string rowType = opts.RowName (dt.TableName, gen);
1154 m.Name = "Add" + rowType;
1155 m.ReturnType = TypeRef (rowType);
1156 m.Attributes = MemberAttributes.Public;
1158 m.Statements.Add (VarDecl (rowType, "row", MethodInvoke ("New" + rowType)));
1160 foreach (DataColumn col in dt.Columns) {
1161 if (col.ColumnMapping == MappingType.Hidden) {
1162 foreach (DataRelation r in dt.DataSet.Relations) {
1163 if (r.ChildTable == dt) {
1165 string paramType = opts.RowName (r.ParentTable.TableName, gen);
1166 string paramName = paramType;
1167 m.Parameters.Add (Param (paramType, paramName));
1168 // CODE: SetParentRow (fooRow, DataSet.Relations ["foo_bar"]);
1169 m.Statements.Add (Eval (MethodInvoke (Local ("row"), "SetParentRow", ParamRef (paramName), IndexerRef (PropRef (PropRef ("DataSet"), "Relations"), Const (r.RelationName)))));
1176 string paramName = opts.ColumnName (col.ColumnName, gen);
1177 m.Parameters.Add (Param (col.DataType, paramName));
1178 // row ["foo"] = foo;
1179 m.Statements.Add (Let (IndexerRef (Local ("row"), Const (paramName)), ParamRef (paramName)));
1184 m.Statements.Add (MethodInvoke (PropRef ("Rows"), "Add", Local ("row")));
1185 m.Statements.Add (Return (Local ("row")));
1190 private CodeMemberMethod CreateTableNewRow (DataTable dt)
1192 CodeMemberMethod m = new CodeMemberMethod ();
1193 string rowType = opts.RowName (dt.TableName, gen);
1194 m.Name = "New" + rowType;
1195 m.ReturnType = TypeRef (rowType);
1196 m.Attributes = MemberAttributes.Public;
1197 m.Statements.Add (Return (Cast (rowType, MethodInvoke ("NewRow"))));
1201 private CodeMemberMethod CreateTableNewRowFromBuilder (DataTable dt)
1203 CodeMemberMethod m = new CodeMemberMethod ();
1204 m.Name = "NewRowFromBuilder";
1205 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1206 m.ReturnType = TypeRef (typeof (DataRow));
1207 m.Parameters.Add (Param (typeof (DataRowBuilder), "builder"));
1208 m.Statements.Add (Return (New (opts.RowName (dt.TableName, gen), ParamRef ("builder"))));
1212 private CodeMemberMethod CreateTableRemoveRow (DataTable dt)
1214 CodeMemberMethod m = new CodeMemberMethod ();
1215 string rowType = opts.RowName (dt.TableName, gen);
1216 m.Name = "Remove" + rowType;
1217 m.Attributes = MemberAttributes.Public;
1218 m.Parameters.Add (Param (TypeRef (rowType), "row"));
1219 m.Statements.Add (Eval (MethodInvoke (PropRef ("Rows"), "Remove", ParamRef ("row"))));
1223 private CodeMemberMethod CreateTableGetRowType (DataTable dt)
1225 CodeMemberMethod m = new CodeMemberMethod ();
1226 m.Name = "GetRowType";
1227 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1228 m.ReturnType = TypeRef (typeof (Type));
1229 m.Statements.Add (Return (new CodeTypeOfExpression (opts.RowName (dt.TableName, gen))));
1233 private CodeMemberMethod CreateTableEventStarter (DataTable dt, string type)
1235 CodeMemberMethod m = new CodeMemberMethod ();
1236 m.Name = "OnRow" + type;
1237 m.Attributes = MemberAttributes.Family | MemberAttributes.Override;
1238 m.Parameters.Add (Param (typeof (DataRowChangeEventArgs), "e"));
1240 m.Statements.Add (Eval (MethodInvoke (
1244 string eventName = opts.TableMemberName (dt.TableName, gen) + "Row" + type;
1245 CodeStatement trueStmt = Eval (
1246 new CodeDelegateInvokeExpression(
1247 new CodeEventReferenceExpression (This (), eventName),
1250 opts.EventArgsName (dt.TableName, gen),
1251 Cast (opts.RowName (dt.TableName, gen), PropRef (ParamRef ("e"), "Row")),
1252 PropRef (ParamRef ("e"), "Action"))));
1255 new CodeConditionStatement (
1256 Inequals (EventRef (eventName), Const (null)),
1257 new CodeStatement [] {trueStmt},
1258 new CodeStatement [] {}));
1263 private CodeMemberEvent CreateTableEvent (DataTable dt, string nameSuffix)
1265 CodeMemberEvent cme = new CodeMemberEvent ();
1266 cme.Attributes = MemberAttributes.Public;
1267 cme.Name = opts.TableMemberName (dt.TableName, gen) + nameSuffix;
1268 cme.Type = TypeRef (opts.TableDelegateName (dt.TableName, gen));
1278 public CodeTypeDeclaration GenerateDataRowType (DataTable dt)
1280 CodeTypeDeclaration t = new CodeTypeDeclaration ();
1281 t.Name = opts.RowName (dt.TableName, gen);
1282 t.BaseTypes.Add (TypeRef (typeof (DataRow)));
1284 t.Members.Add (CreateRowCtor (dt));
1286 t.Members.Add (CreateRowTableField (dt));
1288 foreach (DataColumn col in dt.Columns) {
1289 if (col.ColumnMapping != MappingType.Hidden) {
1290 t.Members.Add (CreateRowColumnProperty (dt, col));
1291 t.Members.Add (CreateRowColumnIsNull (dt, col));
1292 t.Members.Add (CreateRowColumnSetNull (dt, col));
1296 foreach (DataRelation rel in dt.ParentRelations)
1297 t.Members.Add (CreateRowParentRowProperty (dt, rel));
1298 foreach (DataRelation rel in dt.ChildRelations)
1299 t.Members.Add (CreateRowGetChildRows (dt, rel));
1304 private CodeConstructor CreateRowCtor (DataTable dt)
1306 CodeConstructor c = new CodeConstructor ();
1307 c.Attributes = MemberAttributes.Assembly;
1308 c.Parameters.Add (Param (typeof (DataRowBuilder), "builder"));
1309 c.BaseConstructorArgs.Add (ParamRef ("builder"));
1310 c.Statements.Add (Let (FieldRef (GetRowTableFieldName (dt)), Cast (
1311 opts.TableTypeName (dt.TableName, gen),
1312 PropRef ("Table"))));
1316 private string GetRowTableFieldName (DataTable dt)
1318 return "table" + dt.TableName;
1320 private CodeMemberField CreateRowTableField (DataTable dt)
1322 CodeMemberField f = new CodeMemberField ();
1323 f.Name = GetRowTableFieldName (dt);
1324 f.Type = TypeRef (opts.TableTypeName (dt.TableName, gen));
1328 private CodeMemberProperty CreateRowColumnProperty (DataTable dt, DataColumn col)
1330 CodeMemberProperty p = new CodeMemberProperty ();
1331 p.Name = opts.ColumnName (col.ColumnName, gen);
1332 p.Type = TypeRef (col.DataType);
1333 p.Attributes = MemberAttributes.Public;
1335 // This part should be better than MS code output.
1337 // object ret = this [col];
1338 // if (ret == DBNull.Value)
1339 // throw new StrongTypingException ()
1341 // return (type) ret;
1342 p.GetStatements.Add (VarDecl (typeof (object), "ret",
1344 (PropRef (GetRowTableFieldName (dt)),
1345 opts.TableColName (col.ColumnName, gen) + "Column"))));
1346 p.GetStatements.Add (new CodeConditionStatement (
1349 PropRef (TypeRefExp (typeof (DBNull)), "Value")),
1350 new CodeStatement [] {
1351 Throw (New (typeof (StrongTypingException), Const ("Cannot get strong typed value since it is DB null."), Const (null))) },
1352 new CodeStatement [] {
1353 Return (Cast (col.DataType, Local ("ret"))) }));
1355 p.SetStatements.Add (Let (IndexerRef (PropRef (PropRef (GetRowTableFieldName (dt)), opts.TableColName (col.ColumnName, gen) + "Column")), new CodePropertySetValueReferenceExpression ()));
1360 private CodeMemberMethod CreateRowColumnIsNull (DataTable dt, DataColumn col)
1362 CodeMemberMethod m = new CodeMemberMethod ();
1363 m.Name = "Is" + opts.ColumnName (col.ColumnName, gen) + "Null";
1364 m.Attributes = MemberAttributes.Public;
1365 m.ReturnType = TypeRef (typeof (bool));
1366 m.Statements.Add (Return (MethodInvoke (
1368 // table[foo].[bar]Column
1370 PropRef (GetRowTableFieldName (dt)),
1371 opts.TableColName (col.ColumnName, gen) + "Column"))));
1375 private CodeMemberMethod CreateRowColumnSetNull (DataTable dt, DataColumn col)
1377 CodeMemberMethod m = new CodeMemberMethod ();
1378 m.Name = "Set" + opts.ColumnName (col.ColumnName, gen) + "Null";
1379 m.Attributes = MemberAttributes.Public;
1380 m.Statements.Add (Let (IndexerRef (
1382 PropRef (GetRowTableFieldName (dt)),
1383 opts.TableColName (col.ColumnName, gen) + "Column")),
1384 PropRef (TypeRefExp (typeof (DBNull)), "Value")));
1389 private CodeMemberProperty CreateRowParentRowProperty (DataTable dt, DataRelation rel)
1391 CodeMemberProperty p = new CodeMemberProperty ();
1392 p.Name = opts.TableMemberName (rel.ParentTable.TableName, gen) + "Row" +
1393 (rel.ParentTable.TableName == rel.ChildTable.TableName ? "Parent" : String.Empty);
1394 p.Attributes = MemberAttributes.Public;
1395 p.Type = TypeRef (opts.RowName (rel.ParentTable.TableName, gen));
1396 p.GetStatements.Add (Return (Cast (p.Type, MethodInvoke (
1404 Const (rel.RelationName))))));
1405 p.SetStatements.Add (Eval (MethodInvoke (
1407 new CodePropertySetValueReferenceExpression (),
1414 Const (rel.RelationName)))));
1419 private CodeMemberMethod CreateRowGetChildRows (DataTable dt, DataRelation rel)
1421 CodeMemberMethod m = new CodeMemberMethod ();
1422 m.Name = "Get" + opts.TableMemberName (rel.ChildTable.TableName, gen) + "Rows";
1423 m.Attributes = MemberAttributes.Public;
1424 m.ReturnType = new CodeTypeReference (opts.RowName (rel.ChildTable.TableName, gen), 1);
1425 m.Statements.Add (Return (Cast (m.ReturnType, MethodInvoke (
1433 Const (rel.RelationName))))));
1443 // public class [foo]ChangeEventArgs : EventArgs
1445 // private [foo]Row eventRow;
1446 // private DataRowAction eventAction;
1451 private CodeTypeDeclaration GenerateEventType (DataTable dt)
1453 CodeTypeDeclaration t = new CodeTypeDeclaration ();
1454 t.Name = opts.EventArgsName (dt.TableName, gen);
1455 t.BaseTypes.Add (TypeRef (typeof (EventArgs)));
1456 t.Attributes = MemberAttributes.Public;
1459 new CodeMemberField (
1460 TypeRef (opts.RowName (dt.TableName, gen)),
1463 new CodeMemberField (
1464 TypeRef (typeof (DataRowAction)), "eventAction"));
1465 t.Members.Add (CreateEventCtor (dt));
1467 t.Members.Add (CreateEventRow (dt));
1469 t.Members.Add (CreateEventAction (dt));
1475 // public [foo]RowChangeEventArgs ([foo]Row r, DataRowAction a)
1480 private CodeConstructor CreateEventCtor (DataTable dt)
1482 CodeConstructor c = new CodeConstructor ();
1483 c.Attributes = MemberAttributes.Public;
1484 c.Parameters.Add (Param (TypeRef (opts.RowName (dt.TableName, gen)), "r"));
1485 c.Parameters.Add (Param (TypeRef (typeof (DataRowAction)), "a"));
1486 c.Statements.Add (Let (FieldRef ("eventRow"), ParamRef ("r")));
1487 c.Statements.Add (Let (FieldRef ("eventAction"), ParamRef ("a")));
1493 // public [foo]Row Row {
1494 // get { return eventRow; }
1496 private CodeMemberProperty CreateEventRow (DataTable dt)
1498 CodeMemberProperty p = new CodeMemberProperty ();
1500 p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
1501 p.Type = TypeRef (opts.RowName (dt.TableName, gen));
1503 p.GetStatements.Add (Return (FieldRef ("eventRow")));
1508 // public DataRowAction Action {
1509 // get { return eventAction; }
1511 private CodeMemberProperty CreateEventAction (DataTable dt)
1513 CodeMemberProperty p = new CodeMemberProperty ();
1515 p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
1516 p.Type = TypeRef (typeof (DataRowAction));
1518 p.GetStatements.Add (Return (FieldRef ("eventAction")));
1528 /* =========================================================
1531 MonoDataSetGenerator API notes
1535 CreateDataSetClasses (
1539 GeneratorOptions options)
1543 *** Code naming method delegate
1545 public delegate string CodeNamingMethod (string sourceName);
1547 It is used in CodeGeneratorOptions (describled immediately below).
1551 *** Generator Options
1553 public bool MakeClassesInsideDataSet
1554 indicates whether classes and delegates other than DataSet
1555 itself are "contained" in the DataSet class or not.
1557 public CodeNamingMethod CreateDataSetName;
1558 public CodeNamingMethod CreateTableTypeName;
1559 public CodeNamingMethod CreateTableMemberName;
1560 public CodeNamingMethod CreateColumnName;
1561 public CodeNamingMethod CreateRowName;
1562 public CodeNamingMethod CreateRelationName;
1563 public CodeNamingMethod CreateTableDelegateName;
1564 public CodeNamingMethod CreateEventArgsName;
1565 Custom methods each of that returns type or member name.
1567 By default, they are set as to useTypedDataSetGenerator.
1568 CreateIdName() with modifications listed as below:
1571 TableTypeName: "DataTable" suffix
1572 TableMemberName: as is
1574 RowName: "Row" suffix
1575 RelationName: (TBD; maybe had better have another delegate type)
1576 DelegateName: "RowChangedEventHandler" suffix
1577 EventArgsName: "RowChangedEventArgs" suffix
1579 ** Auto Generated classes
1581 1. Custom DataSet class
1583 class name = dataset name, encoded by options.CreateDataSetName().
1587 public default .ctor()
1589 set custom delegate on Tables.CollectionChanged
1590 set custom delegate on Relations.CollectionChanged
1592 runtime serialization .ctor()
1597 data tables: [foo]DataTable foo { return this.table[foo]; }
1600 init variables on new dataset.
1602 *** protected members
1604 ShouldSerializeTables()
1605 returns false, while default DataSet returns true.
1606 ShouldSerializeRelations()
1607 returns false, while default DataSet returns true.
1609 ReadXmlSerializable() ... similar to runtime serialization
1612 GetSchemaSerializable()
1613 Write its schema to temporary MemoryStream
1614 Read XML schema from the stream
1616 *** internal members
1619 set member fields (tables, relations)
1620 call members' "init variables"
1623 set DataSetName, Prefix, Namespace, Locale, CaseSensitive, EnforceConstraints
1627 create FKC: new FKC([rel], new DataColumn [] {table[foo].[keyColumnName]Column}, new DataColumn [] {table[child].[childColName]Column}
1628 fill Rule properties.
1629 allocate relation[rel] and fill Nested, then Relations.Add()
1633 data tables: [foo]DataTable table[foo];
1635 data relations: DataRelation relation[rel];
1637 ShouldSerialize[foo]
1641 2. Custom DataTable classes for each DataTable
1643 This class is created under the dataset.
1645 *** internal members
1647 .ctor() : base("[foo]")
1653 DataColumn [bar]Column { return column[bar]; }
1656 fill each column fields
1660 int Count { rowcount }
1662 this [int index] { row [i]; }
1664 event [foo]RowChangedEventHandler [foo]RowChanged
1665 event [foo]RowChangedEventHandler [foo]RowChanging
1666 event [foo]RowChangedEventHandler [foo]RowDeleted
1667 event [foo]RowChangedEventHandler [foo]RowDeleting
1669 void Add[foo]Row ([foo]Row row) { Rows.Add (row); }
1671 [foo]Row Add[foo]Row ([columnType] [columnName])
1672 create new [foo]row.
1676 // non-relation-children are just created as column type
1677 // relation-children are typeof fooRow[]
1679 GetEnumerator() { Rows.GetEnumerator (); }
1681 override DataTable Clone()
1684 [foo]Row New[foo]Row()
1686 void Remove[foo]Row([foo]Row)
1688 //for each ChildRelations
1689 [bar]Row [] Get[foo_bar]Rows ()
1691 *** protected members
1693 override DataTable CreateInstance() { return new }
1695 override DataRow NewRowFromBuilder(DataRowBuilder)
1697 override Type GetRowType()
1699 override void OnRowChanged(DataRowChangedEventArgs)
1701 check this event [foo]RowChanged.
1703 override void OnRowChanging(DataRowChangedEventArgs)
1704 override void OnRowDeleted(DataRowChangedEventArgs)
1705 override void OnRowDeleting(DataRowChangedEventArgs)
1712 column[bar] = new DataColumn (...);
1716 DataColumn [bar]Column
1718 3. Custom DataRow classses
1725 get { try { } catch { throw StrongTypingException(); }
1726 set { this [[foo]Table.[bar]Column] = value; }
1729 IsNull ([foo]Table.[bar]Column);
1731 void Set[bar]Null ()
1733 if the table is parent of some relations
1735 public [child]Row [] Get[child]Rows()
1737 *** internal members
1739 .ctor(DataRowBuilder) : base.()
1744 [foo]DataTable table[foo]
1747 4. Custom DataRowChangeEvent classes
1752 DataRowAction eventAction
1756 .ctor([foo]Row row, DataRowAction action)
1760 DataRowAction Action
1764 5. public Table RowChangedEventHandler delegates
1766 [foo]RowChangedEventHandler(object, [foo]RowChangedEvent e)
1769 ======================================================== */