Article Options
Recently Viewed
Premium Sponsor
Premium Sponsor

 »  Home  »  Windows Development  »  CodeDOM: How to achieve code generation in .NET - Part 1
CodeDOM: How to achieve code generation in .NET - Part 1
by Paul Nichols | Published  01/29/2003 | Windows Development | Rating:
Paul Nichols

Based in the UK I've been an IT contractor for over 5 years specialising in VB.NET and C# both on both Windows and Web based projects. Please feel free to contact me at mail@pandesolutions.co.uk or see my online CV at www.pandesolutions.co.uk

View all articles by Paul Nichols...

CodeDOM: How to achieve code generation in .NET - Part 1

Article source code: codedom_1.zip

Hopefully over the following weeks these articles will, if nothing else, bring the possibility of generating code with .NET to your attention. More than that though I hope you will actually find a use for The CodeDOM and follow these articles to generate code and complied assemblies. Along the way I'll try to highlight some pitfalls that I have become aware of though being part of a company that has VSIP membership. The code samples will be in VB, the terminology in the most part will be VB orientated too. The generated code will be in both languages though, demonstrating the main use of the CodeDOM. Sorry C# developers, I thought it would make a change!

Requirements

  1. Visual Studio.NET Professional, or Enterprise Architect Edition
  2. VB.NET or C#.NET Programming Knowledge

CodeDOM Overview

Before reading this document you may want to brush up on some of the concepts and terminology found at the following sites:

System.CodeDom Namespace
CodeDOM Quick Reference

This week is simply an introduction, as I've already said hopefully you will find a use for the CodeDOM which will make any following articles more useful.

Introduction to the Code DOM

To start with I will explain some of the advantages of the CodeDOM and times where I can imagine it being of use. We'll then go on to explaining the first steps into creating simple hieratical objects know as CodeDOM graphs, or CodeDOM trees, that can be taken and built into assemblies or simply used to output source code as shown in the following examples.

The main CodeDOM advantage is language independent code generation.

I've found the CodeDOM useful in projects I been involved in where tools have been created which generate repetitive code, allowing some of the laborious nature of coding an extensible database program to be alleviated. Whenever I create a database program I usually have to create many maintenance screens that have a one-to-one relationship with certain database tables. These are required to allow users after delivery to add maybe another category to certain sections of a program etc. Time is best spent working on the more complicated screens and a tool can be created that "churns out" these similar screens in seconds, and also allows a single point of call when an alteration is required, and therefore re-generation is needed.

Another is the ability to create, compile and execute an assembly at runtime, and in utilising that advantage I have also seen the CodeDOM used quite differently to the first example when used to speed file access. An assembly created on the fly can be populated from maybe an XML configuration file; it is then far faster then to interrogate the assembly for consequent requests.

Lets get started.

Download Test Application

We will gradually build our examples up so that we can generate a class that utilises as many code structure types as I feel necessary to allow you to understand the CodeDOM.

The example I'll be using is a very simplistic bank account class with properties:

  • Account Holder
  • Account Number
  • Current Balance (Read only)

A function that transfers money to another account and returns a success value will be included.

The example will raise an event when the balance goes below zero. The Account class implements an interface called IAccount. The class also has a constructor that allows initiation of the class with an account number and starting balance.

One you've downloaded the sample the first point of interest is the main form frmTest.

From frmTest you'll be able to build up the sample class step-by-step. The buttons on this main form basically call the functions that I will go on to explain in a moment. The return objects from the functions are then passed to the CodeWriter class.

You'll see that I've repeated a lot of function calls on the click events; this is just to ease understanding of the example. I also apologise for the order that members of the class appear; to the best of my knowledge you cannot correct this without having a file output and using the CodeLinePragma object (please contact me if you know any different)?

The example output language defaults to VB but by using the language combo you can change this to C#, showing the beauty of the CodeDOM.

The actual code for IAccount doesn't exist in my example it's simply an imaginary interface that has been referenced for demonstration purposes.

CodeWriter Class

This class will be expanded on through out the course of the articles but for now its purpose is to take CodeDOM objects placed in a hierarchical order of namespace, class, members and return code back to us as a string in our chosen language.

The shared/static class (doesn't require instantiation) contains the public property Language , this allows the choice of output code language. Also there's only one function at the moment call Write that allows a parameter of type CodeNamespace. This parameter contains the whole code hierarchy. Inside the Write function is a select statement that chooses between output language (in this case VB or C#), the code then creates either a VBCodeProvider or a CSharpCodeProvider object. The provider objects then are used to create a Generator. The Providers allow access to code generators and compilers for the relevant language.

The rest of the functionality populates a StringBuilder from a StringWriter stream that is passed to the Generator's GenerateCodeFromNameSpace method, and the contents of the StringBuilder is returned (this being the actual code).

Invoking 'Generate Class' and the CreateClass Function

Next we'll take a look line-by-line at the first function.

Private Sub cmdGenerateClass_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles cmdGenerateClass.Click

Dim NewClass As CodeTypeDeclaration = CreateClass
Dim CodeNamespace As New CodeNamespace("Bank")

    CodeNamespace.Types.Add(NewClass)
    txtcode.Text = CodeWriter.Write(CodeNamespace)

End Sub

The first line of the code runs the function CreateClass. The simple job of CreateClass is to create a class (no surprise there then), by either calling the VB or C# class creation functions. This is the only time in my examples at present that we really need to do something a little different depending on the output language. Next the returned class object is added to a Namespace object, CodeNamespace. The namespace is then passed to the CodeWriter class.

First we will take a look at the function CreateVBClass.

Private Function CreateVBClass() As CodeTypeDeclaration
Dim AccountClass As New CodeTypeDeclaration()

    With AccountClass
        .IsClass = True
        .Name = "BankAccount"
        .Members.Add(New CodeSnippetTypeMember("Implements IAccount"))
        .Comments.Add(New CodeCommentStatement_
            "This VB Class has been generated by the CodeDOM"))
        .Comments.Add(New CodeCommentStatement(""))
    End With
    Return AccountClass

End Function

I've tried to comment my code as much as I can, trying to make as readable as possible (it's probably the most commenting I've done for a while!), but I've left the comments out of the article code segments, they can be found in the actual download.

Firstly we create a CodeTypeDeclaration object state that we wish it to signify a Class, as this property also allows Enum, Interface or Structure to be chosen. We then name the class accordingly.

Next we add some comments and the base types. We are implementing an interface called IAccount, to do this is a little different in VB than C#. In the C# we wouldn't need to inherit from Object but we need to do this in VB so that when we add our further basetypes the CodeDOM knows that they must be interfaces as VB can only inherit from on base class.

Finally we return the class object to the calling function.

Looking at CreateCSharpClass we can see the subtle differences required by C#.

Private Function CreateCSharpClass() As CodeTypeDeclaration
Dim AccountClass As New CodeTypeDeclaration()

    With AccountClass
        .IsClass = True
        .Name = "BankAccount"
        .BaseTypes.Add(New CodeTypeReference("IAccount"))
        .Comments.Add(New CodeCommentStatement_
            "This C# Class has been generated by the CodeDOM"))
        .Comments.Add(New CodeCommentStatement(""))

        .Members.Add(New CodeEntryPointMethod())
    End With
    Return AccountClass

End Function

The first of these differences is the possible need for an Entry Point method. This is achieved by creating a CodeMemberMethod object (as shown else where in this article).

The second is the ability to utilise the BaseTypes collection to add a reference to the interface, IAccount, that the class implements.

Other than those two additions the code is identical for either of the two languages. The class creation is the only time that I have had to make a differentiation between the two output languages within the whole example.

Invoking 'With Fields' and the AddFields Function.

To add field members to the class creation, we have just looked at, requires the following code which calls the AddFields function creating a CodeMemeberFieldObject.

NewClass.Members.AddRange(AddFields)

Beneath is the code for the AddFields function

Private Function AddFields() As CodeMemberField()

Dim AccountHolderField As New CodeMemberField()

    With AccountHolderField
        .Name = "mAccountHolder"
        .Type = New CodeTypeReference(GetType(String))
        .Attributes = MemberAttributes.Private
    End With

Dim AccountNumberField As New CodeMemberField()

    With AccountNumberField
        .Name = "mAccountNumber"
        .Type = New CodeTypeReference(GetType(Int32))
    End With

Dim StartBalanceField As New CodeMemberField()

    With StartBalanceField
        .Name = "mStartBalance"
        .Type = New CodeTypeReference(GetType(Decimal))
    End With

Dim CurrentBalance As New CodeMemberField()

    With CurrentBalance
        .Name = "mCurrentBalance"
        .Type = New CodeTypeReference(GetType(Decimal))
    End With

    Return New CodeMemberField() {AccountHolderFieldAccountNumberField_
        StartBalanceFieldCurrentBalance}

End Function

The account class has three private fields, mAccountHolderField, mAccountNumberField, mStartBalanceField, mCurrentBalance. The function of these fields is to store the state of there corresponding properties or in the case of the mStartBalanceField it's job is simply to store the initial value passed into the constructor.
For each of the fields a CodeMemberField object is created and properties Name and Type are set, also it is necessary to set the scope of the field using the Attributes property. Finally a CodeMemberField array is passed back to the calling code to be added to our class.

Invoking 'With Properties' and the AddProperties Function.

Firstly we need to add the function call -

NewClass.Members.AddRange(AddProperties)

Then looking at the AddProperties function, we see it's one of the larger functions in this example, it mostly just repeats the same code for each of the three properties so we'll just take a look at defining the AccountHolderProperty property –

    Dim AccountHolderProperty As New CodeMemberProperty()
    Dim AccountInterface As New CodeTypeReference("IAccount")

    With AccountHolderProperty
        .Name = "AccountHolder"
        .Type = New CodeTypeReference(GetType(String))
        .Attributes = MemberAttributes.Public
        .HasGet = True
        .HasSet = True
        .ImplementationTypes.Add(AccountInterface)

        Dim AccountHolderReference As New CodeFieldReferenceExpression()
        AccountHolderReference.FieldName = "mAccountHolder"

        .GetStatements.Add(New CodeMethodReturnStatement_
            AccountHolderReference))

        Dim AccountHolderAssignment As New CodeAssignStatement()
        AccountHolderAssignment.Left = AccountHolderReference
        AccountHolderAssignment.Right = New CodeArgumentReferenceExpression_
            "value")
        .SetStatements.Add(AccountHolderAssignment)
        AccountHolderAssignment = Nothing
    End With

To start with we create a CodeMemberProperty called 'AccountHolderProperty' to be returned from this function along with the other properties. Next we create a new instance of a CodeTypeReference, the type we will be referenceing is IAccount as the properties of this class will be implementing members of this interface. As I mentioned earlier I haven't actually gone into defining the structure of IAccount as it's really just for demonstration purposes as it could just confuse matters?

Now we have the property instance, we need to set a few details namely, Type, Attributes (Scope), HasGet (Has a Get accessor), HasSet (has a set accessor), Name and the any types that are implemented (in this case we add the reference to IAccount as mentioned before).

Before we return the Property from this function we need to build the the Get and Set accessors. First the Get, in which we need to create a reference to the private field member mAccountHolder, using the CodeDOM object, CodeFieldReferenceExpression. Now we have a refrence to the field, we need to return it from the function so we use a CodeMethodReturnStatement object, passing the field reference in as the required parameter. The return statement is then taken and added to the Statements collection of the Get accessor. Our generated code will now return the value of the private field, which is exactly what we want.

Now the Set accessor, we'd like to just create a pretty standard set that takes the value assigned to the property and set mAccountHolder to be equal to that value. So to do this we are going to create a CodeAssignStatement, this object has two important properties, they are the left and right hand side of the assignment statement. For the left hand side we can reuse or reference to the private field, mAccountHolder. The right hand side requires us to create a CodeArgumentReferenceExpression to the default 'value' property of a Set accessor (well in VB anyway).

The last step of property creation is to add the return statement to the GetStatement's Statement collection, and the value Assignment statement to the SetStatement's Statement collection.

Invoking 'With Constructor' and the CreateConstructor Function.

    Dim Constructor As New CodeConstructor()
    With Constructor
        .Parameters.Add(New CodeParameterDeclarationExpression(GetType_
            Int32), "accountNumber"))
        .Parameters.Add(New CodeParameterDeclarationExpression(GetType_
            Decimal), "startBalance"))

        Dim FieldReference As New CodeFieldReferenceExpression()
        Dim ArgumentRef As New CodeArgumentReferenceExpression()
        
        ArgumentRef.ParameterName = .Parameters(0).Name
        FieldReference.FieldName = "mAccountNumber"
        Dim AccountNumberAssign As New CodeAssignStatement(FieldReference_
            ArgumentRef)
        .Statements.Add(AccountNumberAssign)

        FieldReference = New CodeFieldReferenceExpression()
        ArgumentRef = New CodeArgumentReferenceExpression()
        ArgumentRef.ParameterName = .Parameters(1).Name
        FieldReference.FieldName = "mStartBalance"
        Dim StartBalanceAssign As New CodeAssignStatement(FieldReference_
            ArgumentRef)

        FieldReference = Nothing
        ArgumentRef = Nothing
        .Statements.Add(StartBalanceAssign)
        StartBalanceAssign = Nothing
    End With
    Return Constructor

In order to create a Constructor we need the aptly named CodeDOM CodeConstructor object. The statements within the Constructors will take the two defined parameters and assign them to their corresponding private field members. In order to understand the code I will just take you through one of the assignments.

To start with then we need to define the parameters, we could have used AddRange but I've added them one at a time for simplicity. The parameters are accountNumber (Int32) and startBalance (Decimal ).

We have created a CodeAssignStatement before but we'll go through it again. The first step in this case is to create a CodeArgumentReferenceExpression (ArgumentRef) that refers to the constructors' parameter accountNumber. Next using a CodeFieldReferenceExpression object we need to make reference to the field mAccountNumber. Using a CodeAssignStatement we assign these two objects to each other and then add the assignment to the constructors' Statements collection. This process is then repeated for each parameter. The Constructor is then returned to the calling code and passed to the CodeWriter class.

Invoking 'With Function' and the AddFunction Function

At this stage we are not including any event demonstration code, notice the overloaded version of the AddFunction, so I've removed that section for now from the following code:

Private Function AddFunction_
    ByVal includeEvent As BooleanAs CodeMemberMethod

Dim FunctionMember As New CodeMemberMethod()
    
    With FunctionMember
        .Name = "TransferFunds"
        .Statements.Add(New CodeCommentStatement_
            "Put the body of the function here that commits the transfer."))
        .Attributes = MemberAttributes.Public

        .Statements.Add(New CodeMethodReturnStatement_
            New CodeSnippetExpression("true")))

        .ReturnType = New CodeTypeReference(GetType(Boolean))
    End With

    Return FunctionMember

End Function

Once a CodeMemberMethod has been created, (a CodeMemberMethod defines both a sub or a function, the differentiation is made by the ReturnType property), we need to set a few basic properties such as Name and Attributes (scope) and the ReturnType (Boolean).

We also have two Statements to add to the function, the first is just a comment using the CodeCommentStatement object, that states any futher function code should go here, in this case the code would action the transfer of money, if we were going into that much detail. The second is the return statement, not surprisingly using the CodeDOM CodeMethodReturnStatement object, and a CodeSnippetExpression (which allows us to add any text we wish) containing the return value of 'True'. The CodeMemberMethod is then returned from this function.

Invoking 'With Event and the AddEvent Function.

There are three parts to adding the demonstration of events. Invoking the OnOverDrawn sub which raises the Event OnOverDrawn (the addition to the previous function that calls the OnOverDrawn sub). Having a protected sub that raises the event means that if the class is inherited from a different action can be taken and also any logic required around raising the event can be placed within the sub which means there is only one section of code to maintain/change and all the calling code will benefit from the change. Finally the definition of the OverDrawn Event.

If we look at these three steps in a sensible order we should start with the definition of the Event:

Private Function AddEvent() As CodeMemberEvent

Dim OverDrawnEvent As New CodeMemberEvent()

    With OverDrawnEvent
        .Name = "OverDrawn"
        .Attributes = MemberAttributes.Public
        .Type = New CodeTypeReference(GetType(EventHandler))
    End With
    Return OverDrawnEvent

End Function

This time we use a CodeMemberEvent object and set the name and Attributes properties. The type of the Event will be an EventHandler, this is set by creating a CodeTypeReference object. Then we just return the CodeMemberEvent back to the calling code.

Lets look at the definition of the OnOverDrawn sub:

Private Function AddOnOverDrawnSub() As CodeMemberMethod

Dim OnOverDrawnSub As New CodeMemberMethod()

    With OnOverDrawnSub
        .Attributes = MemberAttributes.FamilyOrAssembly
        .Name = "OnOverDrawn"
        .Parameters.Add(New CodeParameterDeclarationExpression(GetType_
            EventArgs), "e"))

        Dim OverDrawnEventRef As New CodeEventReferenceExpression_
            New CodeThisReferenceExpression(), "OverDrawn")
        Dim OverDrawnEventInvoke As New CodeDelegateInvokeExpression()
        With OverDrawnEventInvoke
            .TargetObject = OverDrawnEventRef
            .Parameters.Add(New CodeThisReferenceExpression())
            .Parameters.Add(New CodeVariableReferenceExpression("e"))
        End With
        .Statements.Add(OverDrawnEventInvoke)

        OverDrawnEventInvoke = Nothing
        OverDrawnEventRef = Nothing
    End With
    Return OnOverDrawnSub

End Function

As with AddFunction we have created a CodeMemberMethod but this time with no return type and the Attributes property is set to FamilyOrAssembly meaning it is protected. This method accepts a parameter called e and is of type EventArgs as you can see this is achieved by the use of a CodeParameterDeclarationExpression object. We then need to reference the Event OverDrawn using a CodeEventReferenceExpression. This Event reference is added to the Target Property of the CodeDelegateInvokeExpression object, also parameters of Me and e are added to the object. This Delegate invocation is added to the methods Statement collection and the Sub is passed back to the calling code.

Here is the extra section of AddFunction that is added by the overloaded AddFunction with a parameter value of True -

Dim CodeConditionStatement As New CodeConditionStatement()

    With CodeConditionStatement
        .Condition = New CodeBinaryOperatorExpression_
                    New CodeFieldReferenceExpression_
                    New CodeThisReferenceExpression(), "mCurrentBalance"), _
                        CodeBinaryOperatorType.LessThan_
                        New CodePrimitiveExpression(0))

        Dim OnOverDrawnMethodInvoke As New CodeMethodInvokeExpression()

        OnOverDrawnMethodInvoke.Method = New CodeMethodReferenceExpression_
            New CodeThisReferenceExpression(), "OnOverDrawn")

        OnOverDrawnMethodInvoke.Parameters.Add(New CodeSnippetExpression_
            "System.EventArgs.Empty"))

        .TrueStatements.Add(OnOverDrawnMethodInvoke)
    End With
    .Statements.Add(CodeConditionStatement)

We need to create a CodeConditionStatement that will decide if the OnOverDrawn sub should be called. The condition needs to contain a CodeBinaryOperatorExpression that checks to see if the field reference to mCurrentBalance is less than zero (I've used CodePrimitiveExpression to include the integer value of '0' in the comparison).

Next we need to create the Statement to be added to the True part of the comparison (we have no need to define a False statement). This will mean building a CodeMethodInvokeExpression object. The Method property of the CodeMethodInvokeExpression will reference the method OnOverDrawn. Also we need to pass the required parameter into the method, we'll do this with the following line of code -

    CodeSnippetExpression("System.EventArgs.Empty"))

The condition is now complete and is added to the functions Statement collection.

The explanation of the Event calling code means that all sections of the test application have now been covered.

I hope that this small demonstration helps illustrate how to utilise much of the functionality included in the CodeDOM to achieve the code structures that you will undoubtedly require in any CodeDOM projects you embark on yourselves.

To conclude this section of building CodeDOM graphs it has to be said that there is a lot of work required to build event the simplest of elements such as an event of property. But in order to achieve a totally language independent representation of the code you wish to output it is obvious that this is something we have to put up with.

The examples, I feel so far, haven't been complicated but have covered a lot of ground.

Next we'll go one to look a list of the limitations I have experienced so far within the CodeDOM.

Limitations

Below I have listed (in no particular order), limitations that I have encounted in version 1 of the .NET Framework (and in some cases 1.1).Where ever posible I have tied to add workarounds.

LimitationWorkaround
Adding Comments other than atop methods, classes or namespaces is a known limitation.Add a CodeSnippetTypeMember containing the literal text for the comment to the Members collection (in the appropriate order to appear in the proper location). The drawback of this approach is that the comment syntax will not be translated across languages. Build your graph dynamically to substitute comment snippets using language-specific syntax if robust multiple language support for comments between type members is important.
IParser is not implemented or throws errors for both C# or VBNo workaround is needed, as this certainly does not stop you from compiling. The limitation is that you have to ensure the code that you try to compile is statically correct rather than allowing IParser to do the checking for you.
Different languages need specific elements sometimesA Case statement to insert extra code for certain languages such as Start Point in C# (as mentioned in this articles example).
Using the Alias directiveNested namespaces
The CodeDom namespaces contain classes to conceptually represent most programming constructs. Examples of these include: declarations, statements, iterations, arrays, casts, comments, error handling, and others. However, there are limitations to the current implementation of the CodeDOM, which will remain until Microsoft updates the CodeDom namespacesTo represent constructs not presently supported in CodeDOM you can use the "Snippet" classes. These classes allow you to insert literal lines of source code into a compile unit. The classes available for handling snippets include: the CodeSnippetCompileUnit, CodeSnippetExpression, CodeSnippetStatement, and CodeSnippetTypeMember classes. You can use the snippet classes as a generic "catch all" for implementing presently unsupported programming constructs in the CodeDom.
Variable/Field declaration list (int i,j,k;)Change to individual variable declarations. Really to keep code totally readable this is a preferred method anyway.
Pointer typeJagged array type (array of arrays).

Also:

  • Unsafe modifier not supported.
  • ReadOnly modifier not supported.
  • Volatile modifier not supported.
  • Add and Remove accessors for Event not supported.

Useful links

An example of taking C# code and building a CodeDOM tree.
Microsoft .NET CodeDom Technology - Part 1
Microsoft .NET CodeDom Technology - Part 2
If you do not need source code, you can use the classes in System.Reflection.Emit This namespace is designed to be used by script engines and compilers to generate MSIL code or complete assemblies on disk.

Next Time, Part 2: Introduction to the Code Model

How would you rate the quality of this article?
1 2 3 4 5
Poor Excellent
Tell us why you rated this way (optional):

Article Rating
The average rating is: No-one else has rated this article yet.

Article rating:3.36842105263158 out of 5
 19 people have rated this page
Article Score38515
Comments    Submit Comment

Comment #1  (Posted by Munish Sethi on 02/04/2003)

Good article :)

Maybe in a future article can you address what is new in CodeDom Namespace in framework version 1.1?

Munish
 
Comment #2  (Posted by Gabriel on 02/04/2003)

Very clear article.
Out of curiosity could you please tell me why when you generate properties in vb.net you dont include in
the set portion(byVal Value as string)

your gen code

public property city as string
get
return mCity
end get
set '///// (byVal Value as string) IS MISSING
mcity=value
end set

Does what i am saying really matter?
thanks
Gabriel



 
Comment #3  (Posted by Paul Nichols on 02/04/2003)

Gabriel

Thanks for the comment, I'm glad you liked the article.

If you take the properties as they are and paste them into VS the value parameter is added for you.
The examples are really for that kind of purpose, complilation is another thing altogether and something I'll mention in a later article.
But basically the Value parameter is something that is there for backwards compatibility I belive and is not present in C# so therefore the CodeDOM does not produce it's properties in the VB way, but everthing still works fine.

cheers
Paul

 
Comment #4  (Posted by Paul Nichols on 02/04/2003)

Looking at the CodeDom improvements in version 1.1 is something I'm currently doing and I hope to mention in a later article.

cheers
Paul
 
Comment #5  (Posted by Hemant Sathe on 06/24/2003)

This is a very good article. I have extensively used CodeDOM for writing a windows based desktop application. I used 3-Tier model as base framework. I have written code to generate Windows form, Middleware classes and Data Access components. This helped me extensively for doing all my trial errors on architecture. I am able to generate simple classes for the time being as my focus shifted to actual application development. But hope to generate complex structures such as Invoice which contains master details relationships in one single data set.
I am glad that you are working on the limitations of the CodeDOM to improve it further.
Please write an article on how to create a tree structure like class diagram from the code. This can help in modifying the existing classes easily.
Thanks again for a good article.
Hemant
 
Comment #6  (Posted by Gabriel on 07/17/2003)

Hi
any chance of showing us how to generate Catch try finally statement using the codedom

thanks
Gabriel
 
Comment #7  (Posted by Paul Nichols on 07/17/2003)

Hi

I'm probably telling you the obvious but you need to use the following class
System.CodeDom.CodeTryCatchFinallyStatement

I'm just off on holiday else I'd help more

regards
Paul
 
Comment #8  (Posted by Amit Patel on 07/18/2003)

Hi!
A very easy read. Great Job!
Is anyone straightforward and clean way to remove a particular #region from a Function using CodeDom or other techniques?


 
Comment #9  (Posted by Dale Dixon on 08/25/2003)

Good article. You call this Part I. I've been waiting for months for Part II. Is there going to be one?
 
Comment #10  (Posted by Paul Nichols on 08/26/2003)

I'm sorry but part 2 is looking unlightly, you can email with any questions though and I'll try to answer them

I'm glad you liked the article though

Paul
 
Comment #11  (Posted by Ojas Kale on 09/04/2003)

I have a question regarding the program graphs that we generate using CodeDOM. As I see it, it is quite possible to create a semantically incorrect program and still get CodeDOM to generate code for it. For example, I could Create a CodeAssignmentStatement with non-compatible left and right expressions. Or, worse still, create a CodeIterationStatement and not give its InitExpression at all! Or, a program graph that may be acceptable by one language may not be acceptable by another. Have you come across any article that has such information about incorrect Code Generation?


 
Comment #12  (Posted by Ojas Kale on 09/04/2003)

I have a question regarding the program graphs that we generate using CodeDOM. As I see it, it is quite possible to create a semantically incorrect program and still get CodeDOM to generate code for it. For example, I could Create a CodeAssignmentStatement with non-compatible left and right expressions. Or, worse still, create a CodeIterationStatement and not give its InitExpression at all! Or, a program graph that may be acceptable by one language may not be acceptable by another. Have you come across any article that has such information about incorrect Code Generation?


 
Comment #13  (Posted by Paul Nichols on 09/04/2003)

I've not seen anything about incorrect Code Generation I'm afraid.
I guess it's up to us to genereate the correct code, but if you use the compileunits and the parser (which used to have a problem with it) then you can check what you've genereated is correct.

Hope this helps

Paul
 
Comment #14  (Posted by Igor Werner on 09/15/2003)

Hi,

I develop a code generator as a addin für VS.NET. This addin should create code for a Method.
How can I get the code string only for the Method?
e.g.
public static string GetCodeString(CodeCommentStatement commentar,CodeLanguage language)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
ICodeGenerator generator = GetCodeGenerator(language);
generator.GenerateCodeFromStatement(commentar,sw,null);
sw.Close();
sw = null;
generator = null;
return sb.ToString();
}

ICodeGenerator has not a Method to generate Code from CodeTypeMember Object.
Can enybody help me?

Thanks

Igor

Ps.
Sorry for my English.

 
Comment #15  (Posted by alexander leon on 11/12/2003)

thanks for giving your artical for codedom,
now i am working for a project which use codedom,i have some questions, can you anwser them:
1. how to autogenerate a #Region... #End Region code unit in a class
2.how to make a private Member where i should put(it autogenerted a member ,such as string or something else, always infront of properties and methods or functions),i need to have a code just like the following:


private stringA as String

public property propertyA as String
Get
Return stringA
End Get
Set(ByVal Value As String)
stringA = Value
End Set
end property

private stringB as String


private sub subA()
''''''SOME CODE
end sub

private stringCas String


but the codedom always put the members before properties and sub like this:

private stringA as String
private stringB as String
private stringC as String

public property propertyA as String
Get
Return stringA
End Get
Set(ByVal Value As String)
stringA = Value
End Set
end property

private sub subA()
''''''SOME CODE
end sub


can you give me some advices?

thanks

your reader
2003/11/11


 
Comment #16  (Posted by Paul Nichols on 11/12/2003)

Glad you liked the article, I'm afraid as far as I know the only way to add
a region is to add CodeSnippet, and as for the other problem I'm afraid this
is the way the code is generated. you could always go through the code files
and manipulate them. There is also something called CodeLinePragma I'm not
sure if that helps?
 
Comment #17  (Posted by HemaShekar on 03/02/2004)

It's a nice article which cleared lot of doubts regarding CodeDOM. But what i felt was it will be more better even if you give Csharp samples. But anyway thank you for giving clear description about using CodeDOM and send me the further updates to my mail id.
Thank You
 
Comment #18  (Posted by Bruce on 02/08/2005)
Rating
Is there anyway to generate the designer.vb code for a control object using the CodeDom? eg.
Me.Button1.Location = New System.Drawing.Point(13, 13)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"

Given that you have an existing control on a form?
 
Comment #19  (Posted by Arvin on 09/30/2005)
Rating
your article is quite interesting.

I am facing error in the below coding. Pl help
I have given my coding below:

objmail.BodyFormat = MailFormat.Html;
objmail.Priority = MailPriority.High;
objmail.From = "administrator";
objmail.To = strContactEmail;
objmail.Subject = "Support Portal Logon details";

objmail.Body = "Support User ID- " + strContactEmail + " and Password - " + strPassfromDB;
SmtpMail.SmtpServer="Remote server name";
SmtpMail.Send(objmail);
SendMsg.Text = "Logon details has been sent by mail ";
SendMsg.Visible = true;
ErrorMsg.Visible = false;

I am running it in a remote machine.
I am getting error as "The send using configuration value is invalid"

please help me in this.

Regards,

 
Comment #20  (Posted by an unknown user on 07/07/2006)
Rating
This is an excellent article ..Very informative and good to get started.Example is very good.

Arun Vijayraghavan
 
Comment #21  (Posted by an unknown user on 07/07/2006)
Rating
This is an excellent article ..Very informative and good to get started.Example is very good.

Arun Vijayraghavan
 
Comment #22  (Posted by an unknown user on 02/01/2007)
Rating
It is not a limitation to add comments in the method body. Create a CodeCommentStatment and add it to the method statments.
 
Comment #23  (Posted by Bristol Airport Hotels on 04/19/2012)
Rating
EGRFjs Thank you for your post.Really thank you! Really Cool.
 
Sponsored Links