2013-11-09

Windows welcome screen slow

After I log in to Windows 7 the welcome screen stays on for ages, in the past it was almost instant.  I’ve tried various suggestions from forums and none of them worked, then it struck me what it was!

Windows was trying to reconnect network drives after I had logged in, but one of them (a connection to my iMac) was unobtainable because my iMac was off.  I disconnected the mapped network drives and speed is back to normal Smile

2013-11-04

Installing Ruby on Rails, RubyMine and MongoDB on Ubuntu Linux

Here are some really basic instructions which should work on a virgin installation of Ubuntu Linux.  I tried following some instructions in a book but they were awful, these are what I ended up with.

Install some installation helper tools etc

sudo apt-get install build-essential git-core
sudo apt-get install curl
bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
echo '[[ -s "/home/x/.rvm/scripts/rvm" ]] && source "/home/x/.rvm/scripts/rvm"' >> ~/.bashrc
source ~/.bashrc

Install JavaScript interpreter

sudo apt-get install nodejs

Install MongoDB server and clients

sudo apt-get install mongodb-server
sudo apt-get install mongodb-clients

Install Rails

sudo apt-get install rails

Install Ruby 1.9.3 and set it as the default version to use

rvm install 1.9.3
rvm use --default 1.9.3

Install Gems required by Ruby

gem install rails
gem install mongoid
gem install therubyracer

Java JDK for RubyMine

sudo apt-get install openjdk-7-jdk
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/bin

Now download RubyMine from http://www.jetbrains.com/ruby/download/ then extract it and move it to /opt

Start RubyMine, thereafter it will be available in the start menu

cd /opt/RubyMine-5.4.3.2.1/bin

Create a directory for Rails projects and cd into it

mkdir ~/RailsProjects
cd ~/RailsProjects

Create a new rails project without active record

rails new TestMongoDB --skip-active-record

Open the project using RubyMine and edit the GemFile contents, add the following

gem 'bson', '~> 2.0.0.rc2'
gem 'mongoid', git: 'git://github.com/mongoid/mongoid.git'

In RubyMine go to the Tools menu and select Bundler->Install to install the Ruby Gems we have just added to the project.

Create a config file in config/mongoid.yml and paste in the following

development:
  sessions:
    default:
      database: testercles
      hosts:
        - localhost

Go back to your Terminal window to create some data to retrieve

mongo
use testercles
db.Books.save( { Title : "This is the title" })

Create a Book class in app/models/book.rb

require 'rails/mongoid'
class Book
  include Mongoid::Document

  field :Title, type: String
end

In RubyMine go to the Tools menu then “Run rails generator”->Controller (or press ctrl+alt+G then type controller) – name the controller Home

Add the following require to the top of the class file and insert the following index method

require 'mongoid'

  def index
    @book = Book.all.first()
  end

Create a view for this controller/action, you can do this by clicking the icon in the gutterbar to the left of the method name, this will create the view automatically for you.  Set the view html to the following

The book title is: <%= @book.Title %>

Edit config/routes.rb and add the following root

root :to => "home#index"

Now run your app and navigate your browser to http://localhost:3000

2012-12-21

Decorating Unity extension

First I want to give credit where it is due, the code in this post is based largely on the code I found in this post by Jim Chrisopher.
The original code required me to register my decorators before registering the type I wanted to decorate.  I didn't like this because I prefer to register all the low-level services from within their own assemblies and then have the app (website etc) decorate those types at a higher level.  So I changed the code in the following ways
  1. It now uses the UnityContainer.Configure<> method to decorate types.
  2. The decorators may be registered before or after the registered type, or both, it doesn't matter.
  3. It is possible to register both generic and non-generic types, and both will be used if applicable (e.g. ICommand<> and ICommand<string> would apply to Command<string> but only ICommand<> would apply to Command<int>.)
  4. It works with child containers.
  5. It uses the context.NewBuild method instead of requiring an IUnityContainer reference.
The code is used like this
//Program.cs
using System;
using Microsoft.Practices.Unity;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            var container = new UnityContainer();
            container.AddNewExtension<Decorating>();
            container
                .Configure<Decorating>()
                    .Decorate(typeToDecorate: typeof(ICommand<>), decorateWith: typeof(CommandLogger<>))
                .Configure<Decorating>()
                    .Decorate<ICommand<string>, CommandLogger<string>>();

            container.RegisterType(typeof(ICommand<>), typeof(Command<>));

            var intCommand = container.Resolve<ICommand<int>>();
            intCommand.Execute(42);

            var stringCommand = container.Resolve<ICommand<string>>();
            stringCommand.Execute("Hello world");

            Console.ReadLine();
        }
    }
}

//An iterface type to resolve at runtime
using System;

namespace ConsoleApplication5
{
    public interface ICommand<T>
    {
        void Execute(T value);
    }

    public class Command<T> : ICommand<T>
    {
        public Command() 
        {
        }

        public void Execute(T value)
        {
            Console.WriteLine("Command: " + value.ToString());
        }
    }

    public class CommandLogger<T> : ICommand<T>
    {
        readonly ICommand<T> Inner;

        public CommandLogger(ICommand<T> inner)
        {
            this.Inner = inner;
        }

        public void Execute(T value)
        {
            Console.WriteLine("CommandLogger: " + value.ToString());
            Inner.Execute(value);
        }
    }
}



And here it the code which implements the decorating extension. The trick is to allow the normal build up first then set that initial instance as the parameter for creating the first decorator, then that decorator as the parameter for the next decorator to build, and so on.


//DecoratingExtension.cs
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.ObjectBuilder;

namespace ConsoleApplication5
{
    public class Decorating : UnityContainerExtension
    {
        DecoratorTypeRegister Register;

        public Decorating()
            : base() { }

        internal Decorating(IUnityContainer container, DecoratorTypeRegister register)
        {
            container.AddExtension(this);
            this.Register.CopyFrom(register);
        }

        protected override void Initialize()
        {
            this.Register = new DecoratorTypeRegister();
            this.Context.ChildContainerCreated += Context_ChildContainerCreated;
            Context.Strategies.Add(
                    new DecoratingBuildStrategy(Register),
                    UnityBuildStage.PreCreation
            );
        }

        void Context_ChildContainerCreated(object sender, ChildContainerCreatedEventArgs e)
        {
            var decoratingExtension = new Decorating(e.ChildContainer, Register);
        }

        public IUnityContainer Decorate(Type typeToDecorate, Type decorateWith)
        {
            Register.Register(typeToDecorate: typeToDecorate, decorateWith: decorateWith);
            return Container;
        }

        public IUnityContainer Decorate<TTypeToDecorate, TDecorateWith>()
        {
            Decorate(typeof(TTypeToDecorate), typeof(TDecorateWith));
            return Container;
        }
    }
}


//DecoratingBuildStrategy.cs
using System;
using System.Collections.Generic;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;

namespace ConsoleApplication5
{
    internal class DecoratingBuildStrategy : BuilderStrategy
    {
        readonly DecoratorTypeRegister Register;

        internal DecoratingBuildStrategy(DecoratorTypeRegister register)
        {
            this.Register = register;
        }

        public override void PostBuildUp(IBuilderContext context)
        {
            base.PostBuildUp(context);
            Type typeRequested = context.OriginalBuildKey.Type;
            if (!typeRequested.IsInterface)
                return;

            Type typeToBuild = context.BuildKey.Type;

            if (!Register.HasDecorators(typeRequested))
                return;

            var typeStack = new Stack<Type>(Register.GetDecoratorTypes(typeRequested));

            typeStack.ForEach(decoratorType =>
            {
                DependencyOverride dependencyOverride = new DependencyOverride(
                        typeToConstruct: typeRequested,
                        dependencyValue: context.Existing
                    );

                Type actualTypeToBuild = decoratorType;
                if (actualTypeToBuild.IsGenericTypeDefinition)
                {
                    Type[] genericArgumentTypes = context.OriginalBuildKey.Type.GetGenericArguments();
                    actualTypeToBuild = actualTypeToBuild.MakeGenericType(genericArgumentTypes);
                }

                context.AddResolverOverrides(dependencyOverride);
                context.Existing = context.NewBuildUp(new NamedTypeBuildKey(actualTypeToBuild));
            });
        }
    }
}

//DecoratingTypeRegister
using System;
using System.Collections.Generic;

namespace ConsoleApplication5
{
    internal class DecoratorTypeRegister
    {
        readonly Dictionary<Type, List<Type>> DecoratedTypes;

        public DecoratorTypeRegister()
        {
            this.DecoratedTypes = new Dictionary<Type, List<Type>>();
        }

        public void Register(
            Type typeToDecorate,
            Type decorateWith)
        {
            if (typeToDecorate == null)
                throw new ArgumentNullException("TypeToDecorate");
            if (!typeToDecorate.IsInterface)
                throw new ArgumentException("TypeToDecorate must be an interface");
            if (decorateWith == null)
                throw new ArgumentNullException("DecorateWith");

            List<Type> registeredDecoratorTypes;
            if (!DecoratedTypes.TryGetValue(typeToDecorate, out registeredDecoratorTypes))
            {
                registeredDecoratorTypes = new List<Type>();
                DecoratedTypes.Add(typeToDecorate, registeredDecoratorTypes);
            }
            registeredDecoratorTypes.Add(decorateWith);
        }

        public void Register<TTypeToDecorate, TDecorateWith>(
            TTypeToDecorate typeToDecorate,
            TDecorateWith decorateWith)
        {
            Register(typeToDecorate: typeof(TTypeToDecorate), decorateWith: typeof(TDecorateWith));
        }

        public IEnumerable<Type> GetDecoratorTypes(Type typeToDecorate)
        {
            if (typeToDecorate == null)
                throw new ArgumentNullException("TypeToDecorate");
            if (!typeToDecorate.IsInterface)
                throw new ArgumentException("TypeToDecorate must be an interface");

            var result = new List<Type>();
            List<Type> registeredDecoratorTypes;
            if (DecoratedTypes.TryGetValue(typeToDecorate, out registeredDecoratorTypes))
                result.AddRange(registeredDecoratorTypes);
            if (typeToDecorate.IsGenericType)
                if (DecoratedTypes.TryGetValue(typeToDecorate.GetGenericTypeDefinition(), out registeredDecoratorTypes))
                    result.AddRange(registeredDecoratorTypes);
            return result;
        }

        public IEnumerable<Type> GetDecoratorTypes<TTypeToDecorate>()
        {
            return GetDecoratorTypes(typeof(TTypeToDecorate));
        }

        public bool HasDecorators(Type decoratorType)
        {
            return DecoratedTypes.ContainsKey(decoratorType) ||
                (decoratorType.IsGenericType && DecoratedTypes.ContainsKey(decoratorType.GetGenericTypeDefinition()));
        }

        internal void CopyFrom(DecoratorTypeRegister register)
        {
            foreach (var item in register.DecoratedTypes)
            {
                List<Type> decoratorTypeList;
                if (!DecoratedTypes.TryGetValue(item.Key, out decoratorTypeList))
                {
                    decoratorTypeList = new List<Type>();
                    DecoratedTypes.Add(item.Key, decoratorTypeList);
                }
                decoratorTypeList.AddRange(item.Value);
            }
        }
    }
}

2012-08-29

SpinLock SynchronizationLockException - The calling thread does not hold the lock

Here is the code from a console app.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication48
{
class Program
{
static readonly SpinLock SpinLock = new SpinLock();
static void Main(string[] args)
{
bool lockTaken = false;
try
{
SpinLock.Enter(
ref lockTaken);
if (lockTaken)
Console.WriteLine(
"Lock taken");
}
finally
{
if (lockTaken)
SpinLock.Exit();
}
Console.WriteLine(
"Done");
}
}
}


So why would this single-threaded app tell me that the thread trying to call SpinLock.Exit() doesn’t hold the lock?



SpinLock is a value type.  When you mark a field referencing a reference type as readonly you are not only making the field unassignable but also implicitly making the value immutable.  To achieve this .NET will give you a copy of the value each time you read it rather than returning the original, that way if you change anything you will in fact be changing a copy.  So the call to SpinLock.Enter will execute on one copy of the SpinLock, and SpinLock.Exit will execute on a second copy and thus because they are separate instances the call to Exit will throw an exception because the current thread doesn’t hold a lock on it.



The solution is simple; remove readonly.

C# scripting in .NET

Based on a couple of days of experimenting it seems that I now have C# scripting working in my application to a level that I am satisfied.  Because I couldn’t have achieved this without looking at other people’s examples I thought it was only fair that I share what I now have.  Firstly I want to say that my purpose was to give the user the ability to write procedural code rather than object code.  Although it is still possible for the user to write OOP source code my requirement was to let the user define a function which returned a specific return type.

public interface ICompiledFunction<T>
{
T Execute(Dictionary
<string, object> variables);
}


A typical script might look something like this




public decimal string Main()
{
return "Bob Monkhouse";
}



To create an instance of the ICompiledFunction<T> I use ICompilerService, which is defined like so



public interface ICompilerService
{
bool Compile<T>(
string[] scripts,
Dictionary
<string, Type> variableDefinitions,
IEnumerable
<Assembly> referencedAssemblies,
out ICompiledFunction<T> function,
out string sourceCode,
out IEnumerable<string> compilerErrors);
}




    1. Scripts: An array of methods which should be combined to make the full script.  Each may include its own “using” statements.


    2. VariableDefinitions: A dictionary of variable names with their types.  These will appear to be global variables available to the combined scripts, but in fact they will be properties defined as part of the wrapper class which is generated automatically.


    3. ReferencedAssemblies: A collection of Assembly, used to ensure that the script has access to any types declared.


    4. Function: The compiled function


    5. SourceCode: The complete source code which is compiled after it has been merged; useful for working out what is wrong with your source code.


    6. CompilerErrors: A collection of compiler errors.




The importance of CompilerService is that the implementation will create a new AppDomain each time you call Compile.  When the CompilerService is dispose it will unload all assemblies.  I will post the code with comments inline



using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;

namespace PeterMorris.Scripting
{
public class CompilerService : ICompilerService, IDisposable
{
Stack
<AppDomain> SandboxAppDomains = new Stack<AppDomain>();
bool Disposed;

public bool Compile<T>(
string[] scripts,
Dictionary
<string, Type> variableDefinitions,
IEnumerable
<Assembly> referencedAssemblies,
out ICompiledFunction<T> function,
out string sourceCode,
out IEnumerable<string> compilerErrors)
{
if (scripts == null)
throw new ArgumentNullException("Scripts");

//Define app domain settings such as the code base
var appDomainSetup = new AppDomainSetup();
string appBase = typeof(CompilerService).Assembly.CodeBase;
appBase
= new Uri(appBase).LocalPath;
appDomainSetup.ApplicationBase
= Path.GetDirectoryName(appBase);
var evidence
= AppDomain.CurrentDomain.Evidence;

//Create a uniquely named app domain and push it onto a stack for disposing later
string sandboxAppDomainName = "Sandbox" + Guid.NewGuid().ToString().Replace("-", "");
var sandboxAppDomain
= AppDomain.CreateDomain(sandboxAppDomainName, evidence, appDomainSetup);
SandboxAppDomains.Push(sandboxAppDomain);

//Clone the original scripts, we don't want to alter the originals
scripts = scripts.ToArray();

//Strip out the using clauses from each script so that they can be combined
var usingClauses = StripOutUsingClauses(scripts).OrderBy(x => x).ToList();

//Build the complete source code to be compiled
sourceCode = BuildSourceCode(usingClauses, scripts, variableDefinitions);

CompiledFunction
<T> result;
try
{
//Create an instance of CompiledFunction<T> in the new app domain
result = (CompiledFunction<T>)sandboxAppDomain.CreateInstanceAndUnwrap(
assemblyName:
typeof(CompiledFunction<T>).Assembly.GetName().FullName,
typeName:
typeof(CompiledFunction<T>).FullName);
}
catch (Exception unexpectedException)
{
function
= null;
compilerErrors
= new string[] { unexpectedException.Message };
return false;
}

//Compile the function
//Variable definitions and source code are passed so that we can translate line numbers
//in the error message back to the line number of the snippet of source the user
//has typed in
function = (ICompiledFunction<T>)result;
return result.Compile(
sourceCode: sourceCode,
variableDefinitions: variableDefinitions,
referencedAssemblies: referencedAssemblies,
compilerErrors:
out compilerErrors);
}

public static HashSet<string> StripOutUsingClauses(string[] scripts)
{
//Make a hashset of using clauses, to ensure we have no duplicates
var usingClauses = new HashSet<string>();
//Ensure that the standard using clauses are present
usingClauses.Add("System");
usingClauses.Add(
"System.Linq");
usingClauses.Add(
"System.Collections.Generic");

//Create a regex which matches a using statement
var regex = new Regex(@"^[\s]*using[\s]+(\S*?)[\s]*;[\s]*$", RegexOptions.IgnoreCase);

//Loop through each script
for (int scriptIndex = 0; scriptIndex < scripts.Length; scriptIndex++)
{
string script = scripts[scriptIndex];
if (string.IsNullOrEmpty(script))
continue;

var scriptReader
= new StringReader(script);
var scriptBuilder
= new StringBuilder();
while (true)
{
//Read the next line of the current script, null == end of script
string line = scriptReader.ReadLine();
if (line == null)
break;

//Ignore blank lines
if (line.Trim() == "")
continue;

var match
= regex.Match(line);
if (match.Captures.Count > 0)
{
//If there is a match then add the name to the using clause hash set
string nameSpace = match.Groups[1].Value;
usingClauses.Add(nameSpace);
}
else
{
//If no match then the using clauses are finished, add the rest
//of the text from the reader into the writer
scriptBuilder.AppendLine(line);
scriptBuilder.Append(scriptReader.ReadToEnd());
break;
}
}
//Loop through each line of script

//Replace the script with text without the using clauses
scripts[scriptIndex] = scriptBuilder.ToString();
}
//foreach script
return usingClauses;
}

//Builds the full source code with wrapping class
string BuildSourceCode(List<string> usingClauses, string[] scripts, IEnumerable<KeyValuePair<string, Type>> variableDefinitions)
{
if (usingClauses == null)
throw new ArgumentNullException("usingClauses");

var scriptBuilder
= new StringBuilder();
//Add using clauses
foreach (string nameSpace in usingClauses.OrderBy(x => x))
scriptBuilder.AppendFormat(
"using {0};\r\n", nameSpace);
if (usingClauses.Any())
scriptBuilder.AppendLine();

//namespace
scriptBuilder.AppendLine("namespace Sandbox");
scriptBuilder.AppendLine(
"{");
{
//Wrapper class
scriptBuilder.AppendLine("public class ScriptHolder");
scriptBuilder.AppendLine(
"{");
{
//Add variable definitions as properties within the class
BuildProperties(scriptBuilder, variableDefinitions);

//Combine all scripts as a single string
foreach (string script in scripts)
{
scriptBuilder.AppendLine(script);
scriptBuilder.AppendLine();
}
}
scriptBuilder.AppendLine(
"}"); //class
}
scriptBuilder.AppendLine(
"}"); //namespace
return scriptBuilder.ToString();
}

//Add variable definitions as properties within the script
void BuildProperties(StringBuilder scriptBuilder, IEnumerable<KeyValuePair<string, Type>> variableDefinitions)
{
if (variableDefinitions == null)
return;

foreach (var kvp in variableDefinitions.OrderBy(x => x.Key))
{
//ToScriptableString is required to expand generic types back into
//proper looking source code
string scriptableTypeName = kvp.Value.ToScriptableString();
string variableName = kvp.Key;
scriptBuilder.AppendFormat(
"\tpublic {0} {1};\r\n", scriptableTypeName, variableName);
}
if (variableDefinitions.Any())
scriptBuilder.AppendLine();
}

void Dispose(bool isDisposing)
{
if (Disposed)
return;
Disposed
= true;
if (isDisposing)
//Unload all sandbox app domains,
//in reverse order - just because I have OCD :-)
while (SandboxAppDomains.Count > 0)
AppDomain.Unload(SandboxAppDomains.Pop());
}

public void Dispose()
{
Dispose(
true);
}
}
}


One thing to note here is the use of Type.ToScriptableString() – this is implemented via a helper class.  This is because when you use GetType().FullName on a generic type you get a mangled name which would not compile in a script, so it must be unmangled.



using System;
using System.Text;

namespace PeterMorris.Scripting
{
public static class TypeHelper
{
public static string ToScriptableString(this Type type)
{
if (type == null)
return "Void";

//If not a generic type then just return the full name
if (!type.IsGenericType)
return type.FullName;

//Convert a generic type back to a compilable representation
var builder = new StringBuilder();
Type genericType
= type.GetGenericTypeDefinition();
//Unmangle the name
builder.Append(genericType.Name.Remove(genericType.Name.IndexOf("`")) + "<");
string separator = "";
//Include the inner types of the generic type
foreach (var genericArgument in type.GetGenericArguments())
{
//Recursively call ToScriptableString for the typename, as the inner type
//itself may also be a generic type
builder.AppendFormat("{0}{1}", separator, genericArgument.ToScriptableString());
separator
= ",";
}
builder.Append(
">");
return builder.ToString();
}
}
}


And now the implementing code for CompiledFunction<T>



using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.CSharp;

namespace PeterMorris.Scripting
{
public class CompiledFunction<T> : MarshalByRefObject, ICompiledFunction<T>
{
bool IsCompiled;
Dictionary
<string, Type> VariableDefinitions;
Dictionary
<string, FieldInfo> FieldReferences;
object Instance;
MethodInfo Method;

public CompiledFunction()
{
VariableDefinitions
= new Dictionary<string, Type>();
FieldReferences
= new Dictionary<string, FieldInfo>();
}

public bool Compile(
string sourceCode,
Dictionary
<string, Type> variableDefinitions,
IEnumerable
<Assembly> referencedAssemblies,
out IEnumerable<string> compilerErrors
)
{
if (IsCompiled)
throw new InvalidOperationException("Already compiled");
IsCompiled
= true;

if (variableDefinitions != null)
this.VariableDefinitions = variableDefinitions;

//Get the full path to the executing binary, this is used to find assembly
//references which are not in the GAC. Use Uri to convert to a local path.
string binaryPath = new Uri(AppDomain.CurrentDomain.BaseDirectory).LocalPath;
var fullReferencedAssemblyList
= new List<Assembly>(referencedAssemblies);
//System.dll
fullReferencedAssemblyList.Add(typeof(string).Assembly);
//System.Core.dll
fullReferencedAssemblyList.Add(typeof(IQueryable).Assembly);
//Get assembly names
string[] referencedAssemblyNames =
fullReferencedAssemblyList
.Select(x
=> x.GetName().Name + ".dll")
.Select
(
//If the file exists in the binary folder then add it by full path,
//otherwise add it without a path so that it is assumed to be in the GAC
assemblyName =>
File.Exists(Path.Combine(binaryPath, assemblyName))
?
Path.Combine(binaryPath, assemblyName) :
assemblyName
)
.Distinct()
.ToArray();

//Set the compiler parameters to compile in memory
var compilerparameters = new CompilerParameters
{
GenerateExecutable
= false,
GenerateInMemory
= true,
IncludeDebugInformation
= true,
TreatWarningsAsErrors
= true
};
//Add the list of referenced assemblies
compilerparameters.ReferencedAssemblies.AddRange(referencedAssemblyNames);

//Use C# 3.5 so that we have access to nice features such as LINQ
var options = new Dictionary<string, string>
{
{
"CompilerVersion", "v3.5" }
};

//Create the compiler
var compiler = new CSharpCodeProvider(options);
//Compile the source code
CompilerResults compilerResults;
try
{
compilerResults
= compiler.CompileAssemblyFromSource(
options: compilerparameters,
sources:
new string[] { sourceCode });
}
catch (Exception unexpectedException)
{
compilerErrors
= new string[] { unexpectedException.Message };
return false;
}

var errors
= new List<string>();
if (compilerResults.Errors.Count == 0)
{
//Create an instance of the new class
Instance = compilerResults.CompiledAssembly.CreateInstance("Sandbox.ScriptHolder");
//Find the Main() method
Method = Instance.GetType().GetMethod("Main");
//Report an error if it is not decalred
if (Method == null)
errors.Add(
string.Format("public {0} Main() has not been defined", typeof(T).Name));
else if (!typeof(T).IsAssignableFrom(Method.ReturnType))
//If the Main() method's return type is not assignable to the expected return type
//then report an error
errors.Add(string.Format("Expected return type {0} but found {1}",
typeof(T).FullName, Method.ReturnType.FullName));
}
//Add any compiler errors. FormatError uses the source code and variable definitions
//in order to work out the line number relative to the script entered by the user
//rather than the position in the composite source code
if (compilerResults.Errors != null)
compilerResults.Errors.Cast
<CompilerError>().ToList()
.ForEach(x
=> errors.Add(x.FormatError(sourceCode, variableDefinitions)));

//Create field references (i.e. global variables)
if (!errors.Any())
CreateFieldReferences();
compilerErrors
= errors.ToArray();
return !errors.Any();
}

//Execute the compiled function
public T Execute(Dictionary<string, object> variables)
{
if (!IsCompiled)
throw new InvalidOperationException("Function has not been compiled");

//If we have any variable definitions, set the field references to their default values
if (VariableDefinitions != null)
foreach (var kvp in VariableDefinitions)
{
string fieldName = kvp.Key;
Type fieldType
= kvp.Value;
object defaultValue = fieldType.IsValueType ? Activator.CreateInstance(fieldType) : null;
SetVariable(fieldName, defaultValue);
}

//Set the variables passed by the caller
if (variables != null)
foreach (var kvp in variables)
SetVariable(kvp.Key, kvp.Value);
//Invoke the compiled scripted method
return (T)Method.Invoke(Instance, null);
}

//Populate the FieldReferences list so that it can be built into the composite source code
void CreateFieldReferences()
{
if (VariableDefinitions == null)
return;

foreach (var kvp in VariableDefinitions)
{
string fieldName = kvp.Key;
Type fieldType
= kvp.Value;
FieldInfo fieldInfo
= Instance.GetType().GetField(fieldName);
FieldReferences.Add(fieldName, fieldInfo);
}
}

//Set a field (global variable) value
void SetVariable(string variableName, object value)
{
FieldInfo fieldInfo;
if (!FieldReferences.TryGetValue(variableName, out fieldInfo))
throw new ArgumentException(string.Format("Variable {0} has not been defined", variableName));
fieldInfo.SetValue(Instance, value);
}
}
}


And finally the helper class to reverse the line number from the composite script back to the individual script.



using (var compilerService = new CompilerService())
{
string script = @"
public string Main()
{
return ""Hello "" + Name;
}
";

var scripts
= new string[] { script };
var variableDefinitions
= new Dictionary<string, Type>
{
{
"Name" typeof(string) }
};

string fullSourceCode;
IFunction
<string> function;
IEnumerable
<string> compilerErrors;

if (!compilerService.Compile(
scripts: scripts,
variableDefinitions: variableDefinitions,
referencedAssemblies :
null,
function:
out function,
sourceCode:
out fullSourceCode,
compilerErrors:
out compilerErrors))
{
compilerErrors.ToList()
.ForEach(x
=> Console.WriteLine(x));
return;
}

//Now execute it as many times as you like
var variableValues = new Dictionary<string, object>
{
{
"Name", "Bob Monkhouse" }
};
Console.WriteLine(function(variableValues));

variableValues[
"Name"] = "Peter Poppov";
Console.WriteLine(function(variableValues));
}
//Calls CompilerService.Dispose, which unloads all temporary app domains

Why I dislike DLR

It took me hours last night to work out why I was getting a null result from the Value property in the following code when accessed via IronPython

public interface ISomeInterface
{
decimal Value { get; }
}


How could a non nullable type possibly return a null (or “None”)?  It turns out that when I set my variable using the .NET scripting API



ScriptScope.SetVariable(variableName, (ISomeInterface)value);


The scripting engine still works on the implementing object rather than the interface.  This means that if my object has a method “DoSomethingThatScriptingShouldNotHaveAccessTo()” then scripting has access to it!



In my case this bit me because I had a Nullable<decimal> property called “Value”, and the Value property implemented explicitly for the interface looked like this



decimal ISomeInterface.Value
{
get
{
if (this.Value == null)
CalculateValue();
return this.Value;
}
}


In this case I expected the script to access the variable’s “Value” property via the interface declaration because that is how I typecast the value when setting the variable; but because the DLR accesses the object itself it was going directly to the class’s property itself and fetching a Nullable<Decimal> which of course was null.



The upshot of this is that if I want any kind of control over which methods my users can script I cannot simply have my objects implement specific interfaces, I have to create a facade class for each class I want API access to which has a subset of members and simply passes them through to the real object.  That is going to be a LOT of work!



The DLR should respect the type of the reference passed, not look up GetType() and work on that.  I need a static scripting language for .NET!