|
Trying to replicate the 'InitializeComponent" method of the designer for a form creator I'm building and I can't seem to get the InitializeComponent / Algorithm correct.
Has anyone a link to an article or code snippet dealing specifically with replicating this method?
Thaks,
PAS | | MigrationUser 1 Tuesday, September 21, 2004 3:40 PM | What specifically is the problem you're running into?
The forms designer does several things, but there is nothing special about the InitializeComponent method. The designer simply uses it to initialize the controls and components on the form. | | MigrationUser 1 Tuesday, September 21, 2004 9:59 PM | I'm having trouble generating the code for an InitializeComponent method via CodeDom. I'm building a simple IDE for designing a specific type of form. For each control on the design surface I need to initialize it as does VS.Net's InitializeComponent. Some sample code I've found looks like this:
// build our InitializeComponent method // CodeMemberMethod initComp = new CodeMemberMethod(); initComp.Name = "InitializeComponent"; initComp.ReturnType = new CodeTypeReference("void"); initComp.Attributes = MemberAttributes.Private; initComp.Comments.Add(new CodeCommentStatement()); initComp.Comments.Add(new CodeCommentStatement("Initialize form controls", false)); // add the statements to the init components method // initComp.Statements.Add( new CodeAssignStatement( new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "MyForm"), new CodeObjectCreateExpression( new CodeTypeReference(typeof(System.Windows.Forms.Form).ToString(), 0))));
_class.Members.Add(initComp);
This should generate the following line of source code (abbreviated):
this.MyForm = new MyForm();
It does not seem to be working though so I'm looking for examples of generating an InitializeComponent method via CodeDom.
Thanks.
| | MigrationUser 1 Wednesday, September 22, 2004 11:32 AM | Again, there is nothing special about the InitializeComponent method, at least as far as generating the code goes. You'd generate code for it the same you would any other method. MSDN is a good source for info about code generation using the classes in the System.CodeDom namespace, so I'd start there if you have specific questions.
You didn't mention what was happening when you run this code, so I can only guess. With that said, the code you posted looks fine expect for a couple small problems. This line:initComp.Comments.Add(new CodeCommentStatement()); will cause a NullReferenceException. If you just want the comment characters (// in C#), but no comment text, you can pass an empty string to the contsructor of CodeCommentStatement.
Also, this line may cause problems:initComp.ReturnType = new CodeTypeReference("void");If you want to pass a string for the return type, you should give the full name (System.Void in this case). An overload of the constructor takes a Type object, so you could remove any doubt by passing typeof(System.Void).
Here's some code showing how to generate a class with this method (I don't know whether you need a sample or not, but I love writing code, so here goes anyway ;)) // This is what will hold the whole ball // of wax when we're done CodeCompileUnit codeUnit = new CodeCompileUnit();
// This is the namespace that will contain // our class CodeNamespace ns = new CodeNamespace("WindowsForms.Example");
// And here's the actual class CodeTypeDeclaration myClass = new CodeTypeDeclaration("MyClass");
// I'm guessing you want to derive from Form myClass.BaseTypes.Add(typeof(System.Windows.Forms.Form));
myClass.Members.Add(new CodeMemberField(typeof (System.Windows.Forms.Form), "MyForm"));
// Build the method
/**************************************** * Here's the code you posted ***************************************/
// build our InitializeComponent method //
CodeMemberMethod initComp = new CodeMemberMethod();
initComp.Name = "InitializeComponent";
initComp.ReturnType = new CodeTypeReference("System.Void"); // Full name
initComp.Attributes = MemberAttributes.Private;
initComp.Comments.Add(new CodeCommentStatement("")); // empty string
initComp.Comments.Add(new CodeCommentStatement("Initialize form controls", false));
// add the statements to the init components method
//
initComp.Statements.Add(
new CodeAssignStatement(
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), "MyForm"),
new CodeObjectCreateExpression(
new CodeTypeReference(typeof(System.Windows.Forms.Form).ToString(),
0))));
/************************************ * End posted code section ************************************/
// Add the method to the class... myClass.Members.Add(initComp);
// the class to the namespace... ns.Types.Add(myClass);
// and the namespace to the CodeCompileUnit codeUnit.Namespaces.Add(ns);
// We'll use this to get the code generator CSharpCodeProvider codeProvider = new CSharpCodeProvider();
ICodeGenerator generator = codeProvider.CreateGenerator();
// This isn't strictly necessary. You can just // create a new CodeGeneratorOptions object when // you generate the code and accept the defaults. // I just happen to not like the openening brace on the // same line as the declaration CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BlankLinesBetweenMembers = true; options.ElseOnClosing = false; options.BracingStyle = "C";
// This is what we'll write the generated code to IndentedTextWriter writer = new IndentedTextWriter(new StreamWriter("MyClass.cs"));
// Generate the code, passing the CodeCompileUnit, // output stream, and generator options generator.GenerateCodeFromCompileUnit(codeUnit, writer, options);
// clean up writer.Close();
And here is the contents of MyClass.cs: //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version: 1.1.4322.573 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------
namespace WindowsForms.Example { public class MyClass : System.Windows.Forms.Form { private System.Windows.Forms.Form MyForm; // // Initialize form controls private void InitializeComponent() { this.MyForm = new System.Windows.Forms.Form(); } } } | | MigrationUser 1 Wednesday, September 22, 2004 6:57 PM | Thanks for your efforts. I've pretty much got down the generation of the code. There were a few CodeDom methods I was unaware of that had I taken the time to read more closely would have perhaps saved me some time.
And thaks for your sample code too!
Regards,
Pete | | MigrationUser 1 Thursday, September 23, 2004 10:01 AM | The VisualBasic.NET version of this process:
Imports System.CodeDom Imports System.CodeDom.Compiler Imports System.IO Imports Microsoft.CSharp Imports Microsoft.VisualBasic 'Imports Microsoft.JScript
Module EntryPoint
#Region "Enums" Friend Enum ParserType CSharpCode = 15 VBasicCode = 16 JSharpCode = 17 End Enum #End Region
Private CodeType As ParserType = ParserType.VBasicCode Private CodeProvider As System.CodeDom.Compiler.CodeDomProvider = New VBCodeProvider
Sub Main() ' Create the Unit Dim Unit As CodeCompileUnit = New CodeCompileUnit
' Define a namespace and add Imports statements Dim Namespaces As CodeNamespace = _ New CodeNamespace("Test.CreateForm") Namespaces.Imports.Add( _ New CodeNamespaceImport("System")) Namespaces.Imports.Add( _ New CodeNamespaceImport("System.Drawing")) Namespaces.Imports.Add( _ New CodeNamespaceImport("System.Windows.Forms")) Namespaces.Imports.Add( _ New CodeNamespaceImport("System.Xml")) Namespaces.Imports.Add( _ New CodeNamespaceImport("System.Data"))
Unit.Namespaces.Add(Namespaces)
' Declare the type including base type Dim MyType As CodeTypeDeclaration = _ New CodeTypeDeclaration("Form1") MyType.IsClass = True MyType.TypeAttributes = Reflection.TypeAttributes.Public MyType.BaseTypes.Add("System.Windows.Forms.Form")
Namespaces.Types.Add(MyType)
' Create the constructor/Sub New and add code Dim Constructor As CodeConstructor = _ New CodeConstructor
Constructor.Attributes = MemberAttributes.Public Constructor.Statements.Add( _ New CodeMethodInvokeExpression( _ New CodeThisReferenceExpression, _ "InitializeComponent", New CodeExpression() {}))
MyType.Members.Add(Constructor)
' Declare component container MyType.Members.Add( _ New CodeMemberField("System.ComponentModel. IContainer", "components"))
' Implement the Dispose method Dim DisposeMethod As CodeMemberMethod = _ New CodeMemberMethod
DisposeMethod.Name = "Dispose" DisposeMethod.Attributes = _ MemberAttributes.Family Or MemberAttributes.Overloaded _ Or MemberAttributes.Override
DisposeMethod.Parameters.Add( _ New CodeParameterDeclarationExpression( _ GetType(Boolean), "disposing"))
Dim Statement As CodeConditionStatement = _ New CodeConditionStatement Statement.Condition = _ New CodeArgumentReferenceExpression("disposing")
Dim TrueStatement As CodeConditionStatement = _ New CodeConditionStatement TrueStatement.Condition = _ New CodeBinaryOperatorExpression( _ New CodeArgumentReferenceExpression("components"), _ CodeBinaryOperatorType.IdentityInequality, _ New CodePrimitiveExpression(Nothing))
TrueStatement.TrueStatements.Add( _ New CodeMethodInvokeExpression( _ New CodeFieldReferenceExpression(Nothing, _ "components"), "Dispose", New _ CodeExpression() {}))
Statement.TrueStatements.Add(TrueStatement)
DisposeMethod.Statements.Add(Statement)
DisposeMethod.Statements.Add( _ New CodeMethodInvokeExpression( _ New CodeBaseReferenceExpression, _ "Dispose", New CodeArgumentReferenceExpression() _ {New CodeArgumentReferenceExpression( _ "disposing")}))
MyType.Members.Add(DisposeMethod)
' InitializeComponent Dim InitializeMethod As CodeMemberMethod = New CodeMemberMethod
InitializeMethod.Name = "InitializeComponent" InitializeMethod.Attributes = MemberAttributes.Private
InitializeMethod.CustomAttributes.Add( _ New CodeAttributeDeclaration( _ "System.Diagnostics.DebuggerStepThrough"))
InitializeMethod.Statements.Add( _ New CodeAssignStatement( _ New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression, "components"), _ New CodeObjectCreateExpression( _ New CodeTypeReference( _ GetType(System.ComponentModel.Container)), _ New CodeExpression() {})))
MyType.Members.Add(InitializeMethod)
' Main entry point Dim MainMethod As CodeEntryPointMethod = New CodeEntryPointMethod MainMethod.Name = "Main" MyType.Members.Add(MainMethod)
' Add mouse move event Dim eventstate As New CodeMemberEvent eventstate.Name = "MouseMove" eventstate.Attributes = MemberAttributes.Final Or MemberAttributes.Public eventstate.Type = New CodeTypeReference("System.Windows.Forms.MouseEventHandler") MyType.Members.Add(eventstate)
Dim OutputName As String = "Form1" + GetFileExtension() ' Write the source code Dim sw As StreamWriter = New StreamWriter(OutputName) sw.AutoFlush = True Try Dim Generator As ICodeGenerator = _ (CodeProvider).CreateGenerator
Generator.GenerateCodeFromCompileUnit( _ Unit, sw, Nothing) Finally sw.Close() End Try
' Create the compiler Dim Compiler As ICodeCompiler = _ (CodeProvider).CreateCompiler()
' Create the compiler options ' Include referenced assemblies Dim Options As CompilerParameters = _ New CompilerParameters Options.GenerateExecutable = True Options.OutputAssembly = "TestForm1.exe" Options.CompilerOptions = "/target:winexe" Options.MainClass = "Test.CreateForm.Form1" Options.ReferencedAssemblies.AddRange( _ New String() {"System.dll", "System.Data.dll", _ "System.Drawing.dll", "System.Windows.Forms.dll", _ "System.XML.dll"})
' Build and look for compiler errors Dim Result As CompilerResults = _ Compiler.CompileAssemblyFromFile(Options, OutputName)
Dim E As CompilerError If (Result.Errors.Count > 0) Then For Each E In Result.Errors Console.WriteLine(E.ErrorText) Next Else Console.WriteLine("compiled successfully") End If Console.WriteLine("press enter to continue") Console.ReadLine() End Sub
#Region "GetFileExtension" Private Function GetFileExtension() As String Try Select Case CodeType Case ParserType.CSharpCode Return ".cs" Case ParserType.JSharpCode Return ".jsl" Case ParserType.VBasicCode Return ".vb" End Select Catch ex As Exception
End Try End Function #End Region
End Module
| | MigrationUser 1 Monday, October 11, 2004 12:54 PM |
|