Click here to Skip to main content
11,920,701 members (57,833 online)
Click here to Skip to main content
Add your own
alternative version


24 bookmarked

.NET scripting, a new approach

, 15 Nov 2004
Rate this:
Please Sign up or sign in to vote.
A new(?) approach to scripting in .NET applications.

Sample Image - scripting.png


This project is an example of how to provide scripting support in your application without having to use a scripting host or create a new application domain.


I've come across many articles on how to use C# as a scripting language. All have focused on either shell or runtime scripting. By runtime scripting, I mean scripts that can be modified at runtime with immediate effects in the application. My approach is slightly different. I compile scripts at runtime, but only once. If the user wants to change a script then the application has to be restarted for the changes to have effect. This is a limitation, but I don't feel that it is a serious one. The benefits are the following:

  • No overhead for passing objects over application boundaries
  • No need to specify interfaces between the script and your application
  • Familiar OO-model for scripting

This scripting solution simply allows the user to extend the functionality of any class in your application. All code that is written in the script files will be treated as if it was part of the original code.

Using the code

Presuming that you have a class named ScriptedClass, it's pretty dumb and doesn't utilize all info we are feeding it.

public class ScriptedClass
    private string name;
    public string Name
            return name;

    private int age;
    public int Age
            return age;

    public ScriptedClass()

    public ScriptedClass(string name, int age)

    public virtual string Message
            return string.Format("Hi {0}!", name);

To use the ScripterEngine, you first have to initiate it. The Init-method takes three arguments, one path to the directory that contains the script files, one path to the directory to use for temporary files, and a delegate used for progress:

    string.Format("{0}/script", Application.StartupPath),
    string.Format("{0}/tmp", Application.StartupPath),null);

Then you can create an instance of your class using either any of the constructors.

//Default constructor
ScriptedClass clsa=

//Default constructor, shorter form
ScriptedClass clsb =

//Constructor with arguments
ScriptedClass clsc =
  new Type[]{typeof(string),typeof(int)},
  new object[]{"Hugo",23});

If you, or a user, would like to extend the functionality of this class, you have to write a script.

First, we need a configuration file for the script. This file must be placed in the script directory together with the source file.

<?xml version="1.0" encoding="utf-8" ?>
<ScriptConfiguration name="Intelligent messenger" load="true">

As you can see, it's plain XML. The References tag contains names of assemblies that are necessary to compile the script. We don't really need the System.Web assembly, but I put it there to illustrate the syntax. All loaded assemblies are automatically used as references when compiling the script, so there isn't any need to add references to any basic assemblies.

The Files tag contains all the source files that compose the script. There can be one or more files in a script.

The Types tag contains all the types that are extended by the script. Note that the type must be specified using the full name of the type followed by the name of the assembly the type is defined in.

When we get this file, we can create the file for the actual script.

using ScriptingArchitecture;
using System.Windows.Forms;
using System.Drawing;

namespace Messenger
    public class IntelligentMessage : ScriptingArchitecture.ScriptedClass
        public IntelligentMessage():base()

        public IntelligentMessage(string name, int age):base(name,age)

        public override string Message
                return string.Format("Hi {0}! You are {1} years old!", Name, Age);

Points of Interest

To make it possible to accommodate ad-hoc scripts form different sources, the scripting engine uses inheritance chains. If a bunch of scripts extends a particular class in your application, they must all co-exist. So, in this scenario where your class is A:


The code is rewritten to:


And the class E is supplied when a class of the type A is requested.

What I miss in my scripting implementation is a more sugary syntax for creating scripted objects.

ScriptedClass clsc=(ScriptedClass)ScripterEngine.CreateObject(
    new Type[]{typeof(string),typeof(int)}, 
    new object[]{"Hugo",23});

Isn't exactly beautiful code. I would like something more along the lines with:

ScriptedClass clsc=new ScriptedClass("Hugo",23);

This can be fixed with a static method in ScriptedClass, but I would like a fix to this that is less of a hack.

public static ScriptedClass GetInstance(string name, int age)
    return (ScriptedClass)ScripterEngine.CreateObject(
        new Type[]{typeof(string),typeof(int)},
        new object[]{name,age});


There are some limitations to script code that does not exist in normal development:

  • You are limited to one namespace per source file
  • The class that your script extends must be referenced with its full name, i.e.,
    public class Script : MyApplication.ScriptedObject


    public class Script : ScriptedObject
  • You must implement all constructors that are implemented in the base class.


  • 2004-11-15

    Uploaded the first version.

  • 2004-11-16

    Source file updated and caveats list added.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Hugo Wetterberg
Web Developer
Sweden Sweden
I'm 23 years old and I study informatics at the university of Lund. I'm currently working on my bachelor thesis on predicate logic in .Net.

When it comes to development I'm totally hooked on .Net, it is probably the most exiting platform to work on today, and I'm looking forward to its second incarnation in Longhorn.

You may also be interested in...

Comments and Discussions

QuestionPermission to use this in my own project? Pin
Colin Josey21-Mar-07 14:59
memberColin Josey21-Mar-07 14:59 
AnswerRe: Permission to use this in my own project? Pin
Hugo Wetterberg22-Mar-07 4:53
memberHugo Wetterberg22-Mar-07 4:53 
QuestionFactors Pin
steenhother16-Nov-05 10:58
membersteenhother16-Nov-05 10:58 
I want to merge it into a existing project!!!

Is there anyone there have tried this in VS2003 (is it possible). I can see Hugo have used factors is there any easy way to do something similarly in VS2003.D'Oh! | :doh:
GeneralRegex .NET2 beta 2 issue Pin
Anonymous24-Jun-05 9:11
sussAnonymous24-Jun-05 9:11 
GeneralSecurity Pin
Dave Bacher15-Nov-04 10:02
memberDave Bacher15-Nov-04 10:02 
GeneralRe: Security Pin
Hugo Wetterberg15-Nov-04 22:29
memberHugo Wetterberg15-Nov-04 22:29 
GeneralRe: Security Pin
reinux25-Nov-04 12:18
memberreinux25-Nov-04 12:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.151120.1 | Last Updated 15 Nov 2004
Article Copyright 2004 by Hugo Wetterberg
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid