HOME         User: Anonymous search for  in 
Login
Username:

Password:

Navigation
Registered User Functions:
  1. Register New Account
Anonymous Functions:
  1. Home
  2. Users
  3. Archives
  4. Templates
  5. Articles
  6. MyGeneration Website
  7. MyGeneration Forums
Categories
    Application Type
    1. Command Line
    2. Graphical User Interface
    3. Library
    4. Sample
    5. Web Application
    Architecture Type
    1. Client-Server
    2. Distributed Computing
    3. Multi-Tier
    4. Peer-to-peer
    Operating System
    1. Linux
    2. Win32
    Programming Language
    1. ASP
    2. ASP.Net
    3. C#
    4. C++
    5. Firebird SQL
    6. J#
    7. Java
    8. Jet SQL
    9. JScript
    10. JSP
    11. MySQL
    12. Perl
    13. PHP
    14. PL/SQL
    15. PostgreSQL
    16. SQL
    17. Transact-SQL
    18. VB.Net
    19. VBScript
    20. XSLT
    Article: Developing DotNetScript Templates - MyGeneration
    Author: my.generation
    Type: Tutorial
    Created: 11/17/2004 6:45:59 AM
    Last Updated: 11/17/2004 6:52:12 AM


    Developing DotNetScript Templates - MyGeneration

    Developing DotNetScript Templates with MyGeneration

    Requirements:

    Overview

    MyGeneration currently offers two scripting engines, the Microsoft Scripting Engine, which provides JScript and VBScript support, and DotNetScript, which provides VB.Net and C# support. DotNetScript is not true scripting like the Microsoft Script Control. It actually compiles the code at runtime, then, using reflection, executes code from the resulting compiled .net assembly. This tutorial explains the pros and cons of developing MyGeneration templates using DotNetScript by example. In this example, I will be using C# along with the Nothwind SQL Server database.

    Creating a new C# Template

    • Open MyGeneration.
    • Create a new template by selecting File > New > C# Template from the menu.
    • Edit the templates properties by clicking on the properties icon , or by clicking on the collapsable splitter to the left of the template editor.
    • Fill in the Template Properties form (as seen below).

    • To save your work, select File > Save As ... from the menu. I saved the file as: C:\Program Files\MyGeneration\Templates\DotNetScriptSample.zeus.

    Examine the default template code

    Default Template Body Code (C#)

    Note that, unlike JScript or VBScript, C# templates are initialized with a few lines of code. This default code is very important!!! A C# template MUST have a class named GeneratedTemplate that extends from DotNetScriptTemplate in the template body. MyGeneration instantiates the GeneratedTemplate class, then invokes the Render method to begin the generation process. The majority of template development will occur in the Render method. Try Executing the template and view the results. You will see that the string, "Literal content goes here", will display as the output.

    <%
    public class GeneratedTemplate : DotNetScriptTemplate
    {
    	public GeneratedTemplate(ZeusContext context) : base(context) {}
    
    	public override void Render()
    	{
    %>
    Literal content goes here.
    <%
    	}
    
    }
    %>
    

    Default GUI Code (C#)

    In the template's Interface code, there is also a class called GeneratedGui, which inherits from DotNetScriptGui. Like the Render method in the template body, the Setup method is the starting point for the execution of the User Interface that collects input for the template.

    public class GeneratedGui : DotNetScriptGui
    {
    	public GeneratedGui(ZeusContext context) : base(context) {}
    
    	public override void Setup()
    	{
    	}
    }
    

    Acquiring Input: The Interface Code Block

    In this example, the user needs to select a single table. This can be accomplished in the Interface Code block. The input collected in the interface code will be used in the template body when generating templates.

    Interface Code Block using the MyGeneration API

    Below is a code sample that acquires the required data from the user using the traditional MyGeneration Gui API.

    public class GeneratedGui : DotNetScriptGui
    {
    	public GeneratedGui(ZeusContext context) : base(context) {}
    
    	public override void Setup()
    	{
    		ui.Title = ".NetScript C# Sample: Java Class";
    		ui.Width = 340;
    		ui.Height = 200;
    
    		// Setup Database selection combobox.
    		GuiLabel label_d = ui.AddLabel("lblDatabases", "Select a database:", "Select a database in the dropdown below.");
    		GuiComboBox cmbDatabases = ui.AddComboBox("databaseName", "Select a database.");
    
    		// Setup Tables selection multi-select listbox.
    		GuiLabel label_t = ui.AddLabel("lblTables", "Select table:", "Select table from the combobox below.");
    		GuiComboBox cmbTables = ui.AddComboBox("tableName", "Select a table.");
    
    		// bind data to the controls
    		cmbDatabases.BindData(MyMeta.Databases);
    		cmbDatabases.SelectedValue = MyMeta.DefaultDatabase.Name;
    		cmbTables.BindData( MyMeta.Databases[cmbDatabases.SelectedValue].Tables );
    		
    		
    		// Attach the onchange event to the cmbDatabases control.
    		cmbDatabases.AttachEvent("onchange", "cmbDatabases_onchange");
    
    	
    		ui.ShowGui = true;
    	}
    	
    	public void cmbDatabases_onchange(GuiComboBox control)
    	{
    		GuiComboBox cmbDatabases = ui["databaseName"] as GuiComboBox;
    		GuiComboBox cmbTables = ui["tableName"] as GuiComboBox;
    		
    		cmbTables.BindData( MyMeta.Databases[cmbDatabases.SelectedValue].Tables );
    	}
    }
    

    Interface Code Block using the .Net Windows Forms API (C#)

    Below is an example of a different approach of acquiring the same data without using the MyGeneration GUI API. You'll quickly notice that the code below is just plain old C# Windows Forms code. At the top, there are a special directives that allow the developer to reference assemblies and import namespaces.

    <%#REFERENCE System.Windows.Forms.dll %>
    <%#NAMESPACE System.Windows.Forms %>
    public class GeneratedGui : DotNetScriptGui
    {
    	public GeneratedGui(ZeusContext context) : base(context) {}
    	
    	public override void Setup() 
    	{
    		AcquireInputForm form = new AcquireInputForm(MyMeta, input); 
    
    		if (form.ShowDialog() != DialogResult.OK) 
    		{
    			ui.IsCanceled = true;
    		}
    	}
    }
    
    public class AcquireInputForm : Form
    {
    	private ComboBox cboDatabases = new ComboBox();
    	private ComboBox cboTables = new ComboBox();
    	private Button btnOk = new Button();
    	private dbRoot meta;
    	private IZeusInput input;
    	
    	public AcquireInputForm(dbRoot mymeta, IZeusInput zin)
    	{
    		this.meta = mymeta;
    		this.input = zin;
    	
    		this.BindComboBox(cboDatabases, meta.Databases);
    		cboDatabases.SelectedItem = meta.DefaultDatabase.Name;
    		cboDatabases.Top = 10; cboDatabases.Left = 10; cboDatabases.Width =  200;
    		cboDatabases.SelectedIndexChanged += new EventHandler(cboDatabases_SelectedIndexChanged);
    		
    		this.BindComboBox(cboTables, meta.DefaultDatabase.Tables);
    		cboTables.Top = 50; cboTables.Left = 10; cboTables.Width =  200;
    		
    		btnOk.Text = "Ok";
    		btnOk.Top = 100; btnOk.Left = 10; btnOk.Width = 200;
    		btnOk.Click += new EventHandler(btnOk_Click);
    		
    		this.Controls.AddRange( new Control[] {cboDatabases, cboTables, btnOk} );
    		this.Text = ".NetScript C# Sample: Java Class";
    		this.Width = 230;
    		this.Height = 160;
    	}
    	
    	public void cboDatabases_SelectedIndexChanged(object sender, EventArgs args) 
    	{
    		this.BindComboBox(
    				cboTables, 
    				meta.Databases[ cboDatabases.SelectedItem.ToString() ].Tables 
    			);
    	}
    	
    	public void btnOk_Click(object sender, EventArgs args) 
    	{
    		if ((cboDatabases.SelectedIndex >= 0) &&
    			(cboTables.SelectedIndex >= 0)) 
    		{
    			input["databaseName"] = cboDatabases.SelectedItem.ToString();
    			input["tableName"] = cboTables.SelectedItem.ToString();
    			this.DialogResult = DialogResult.OK;
    			this.Close();
    		}
    		else 
    		{
    			MessageBox.Show("Fill out the required fields.. PLEASE??");
    		}
    	}
    	
    	private void BindComboBox(ComboBox cbo, IEnumerable myMetaCollection)
    	{
    		cbo.Items.Clear();
    		foreach (INameValueItem item in myMetaCollection)
    		{
    			cbo.Items.Add(item.ItemValue);
    		}
    	}
    }
    

    The Template Body

    The template body code block is where the code generation is actually performed. Below is a step by step walkthrough of how I go about developing templates.

    Step 1: Paste desired output into the body of the Render method

    Inside the code sample below, you'll see the the target class I'm looking to generate. This is almost always the first thing I do when I'm starting a new template.

    <%
    public class GeneratedTemplate : DotNetScriptTemplate
    {
    	public GeneratedTemplate(ZeusContext context) : base(context) {}
    
    	public override void Render()
    	{
    		string databaseName = input["databaseName"].ToString();
    		string tableName = input["tableName"].ToString();
    %>/*
     * Employee.java
     *
     * Created on September 23, 2002, 12:59 PM
     */
    
    package com.mygeneration.sample;
    
    import java.sql.*;
    
    import com.mygeneration.businessobjects.*;
    import com.mygeneration.dataaccess.*;
    
    public class Employee extends BizObj
    {
        public Employee() 
        {
        }
              
        // EmployeeID
        public String getEmployeeID()
        {
            return getString(EmployeeSchema.EmployeeID.getFieldName());
        }
        
        public void setEmployeeID(String employeeID)
        {
            setString(EmployeeSchema.EmployeeID.getFieldName(), employeeID);
        }    
    }<%
    	}
    
    }
    %>
    

    Step 2: Add dynamic code

    Add the dynamic code to the template body that replaces the class name, property names, and data types.

    		<%
    public class GeneratedTemplate : DotNetScriptTemplate
    {
    	public GeneratedTemplate(ZeusContext context) : base(context) {}
    
    	public override void Render()
    	{
    		string databaseName = input["databaseName"].ToString();
    		string tableName = input["tableName"].ToString();
    		
    		IDatabase database = MyMeta.Databases[databaseName];
    		ITable table = database.Tables[tableName];
    %>/*
     * <%= table.Alias %>.java
     *
     * Created on <%= DateTime.Now.ToString() %>
     */
    
    package com.mygeneration.sample;
    
    import java.sql.*;
    
    import com.mygeneration.businessobjects.*;
    import com.mygeneration.dataaccess.*;
    
    public class <%= table.Alias %> extends BizObj
    {
        public <%= table.Alias %>() 
        {
        }
    <%
    		foreach (IColumn column in table.Columns)
    		{
    			string datatype = this.GetJavaType(column);
    %>    
        // <%= column.Alias %>
        public <%= datatype %> get<%= column.Alias %>()
        {
            return get<%= datatype %>(<%= table.Alias %>Schema.<%= column.Alias %>.getFieldName());
        }
        
        public void set<%= column.Alias %>(<%= datatype %> m_<%= column.Alias %>)
        {
            set<%= datatype %>(<%= table.Alias %>Schema.<%= column.Alias %>.getFieldName(), m_<%= column.Alias %>);
        }
    <%
    		}
    %>    
    }<%
    	}
    	
    	private string GetJavaType(IColumn column)
    	{
    		string sqlServerType = column.DataTypeName;
    		int charLength = column.CharacterMaxLength;
    		
    		switch (sqlServerType) 
    		{
    			case "bit":
    				return "Boolean";
    			case "decimal":
    			case "float":
    			case "numeric":
    			case "money":
    			case "smallmoney":
    			case "real":
    				return "Decimal";
    			case "tinyint":
    			case "smallint":
    			case "int":
    			case "bigint":
    				return "Integer";
    			case "smalldatetime":
    			case "datetime":
    				return "Timestamp";
    			case "varchar":
    			case "char":
    			case "nvarchar":
    			case "nchar":
    			case "text":
    				if (charLength == 1)
    					return "Character";
    				else
    					return "String";
    			default:
    				return "Object";
    		}
    	}
    }
    %>
    

    Conclusion

    Using DotNetScript, you can take MyGeneration template development to a new level of power and complexity. While dealing with stongly typed classes may be cumbersome compared to variants in VBScript and JScript, DotNetScript provides easy access to all the wonders of the .net framework class library. Keep your eyes open for more related tutorials in the near future.

    Justin Greenwood
    MyGeneration Software
    http://www.mygenerationsoftware.com/
    October 7, 2004

    Messages (by Message)
    Message
    2/12/2007 5:12:01 PM by mfreidge :
    Debugging, How to Single-Step through your Script. See http://www.mygenerationsoftware.com/phpbb2/viewtopic.php?t=32&highlight=debug
    9/18/2005 10:03:41 AM by my.generation :
    Testing the new Email notification system for Articles and Archives.
    Copyright © 2004 MyGeneration Software. All rights reserved.
    Feedback: feedback@mygenerationsoftware.com
    Support: support@mygenerationsoftware.com