Calculator.NET - Calculator that evaluates math expressions

I’d like to announce the release of a little project I’ve been working on. I call it Calculator.NET. I started this project for a couple reasons. First, I was annoyed that Windows Vista doesn’t come with a better calculator. Windows XP has Power Calculator, but that doesn’t work on Vista. Next, I was reading a blog about DynCalc by Bart De Smet on how to do mathematical calculations. That gave me the starting point on how to create Calculator.NET.

As part of the project, I created a MathExpressions library that does the bulk of work. The library supports math expressions, functions unit conversion and variables. Below are some examples of using the library directly.

MathEvaluator eval = new MathEvaluator();
//basic math
double result = eval.Evaluate("(2 + 1) * (1 + 2)");
//calling a function
result = eval.Evaluate("sqrt(4)");
//evaluate trigonometric 
result = eval.Evaluate("cos(pi * 45 / 180.0)");
//convert inches to feet
result = eval.Evaluate("12 [in->ft]");
//use variable
result = eval.Evaluate("answer * 10");
//add variable
eval.Variables.Add("x", 10);
result = eval.Evaluate("x * 10");

Calculator that evaluates math expressions.


Calculator.NET Features

  • Evaluate math expressions including grouping
  • Support trigonometry and other function
  • Common unit conversion of the following types
    • Length
    • Mass
    • Speed
    • Temperature
    • Time
    • Volume
  • Variable support including last answer


XML Serializable Generic Dictionary

For some reason, the generic Dictionary in .net 2.0 is not XML serializable. The following code snippet is a xml serializable generic dictionary. The dictionary is serialzable by implementing the IXmlSerializable interface.

using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

public class SerializableDictionary<TKey, TValue>
    : Dictionary<TKey, TValue>, IXmlSerializable
    #region IXmlSerializable Members
    public System.Xml.Schema.XmlSchema GetSchema()
        return null;

    public void ReadXml(System.Xml.XmlReader reader)
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;

        if (wasEmpty)

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)

            TKey key = (TKey)keySerializer.Deserialize(reader);

            TValue value = (TValue)valueSerializer.Deserialize(reader);

            this.Add(key, value);


    public void WriteXml(System.Xml.XmlWriter writer)
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)

            keySerializer.Serialize(writer, key);

            TValue value = this[key];
            valueSerializer.Serialize(writer, value);


Update: Fixed bug Justin pointed out by adding an extra reader.ReadEndElement() and by checking the IsEmptyElement property.

WilsonORMapper CodeSmith Templates

The following CodeSmith templates are to generate the WilsonORMapper mapping file and to generate the business classes that can be mapped to. These templates have the following features…

  • Converts plural table names to single tense class names
  • Cleans table names to make legal class names
  • Column name cleaning
  • Support for all relationships including many to many
  • Template based, easily changed to meet needs
  • Support for Visual Basic and C#
  • Merge support

Update: These templates are now included with CodeSmith.

MSBuild Community Tasks Project releases new version


The MSBuild Community Tasks Project releases version v1.1.0.145. There are many new tasks in this release. Special thanks to all the contributors to the project.

Current Community Tasks

Task Description
AppPoolController Allows control for an application pool on a local or remote machine with IIS installed.
AppPoolCreate Creates a new application pool on a local or remote machine.
AppPoolDelete Deletes an existing application pool on a local or remote machine.
AssemblyInfo Generates an AssemblyInfo file using the attributes given.
Attrib Changes the attributes of files and/or directories
FileUpdate Replace text in file(s) using a Regular Expression.
FtpUpload Uploads a file using File Transfer Protocol (FTP).
FxCop Uses FxCop to analyze managed code assemblies and reports on their design best-practice compliance.
Mail Sends an email message.
Math.Add Add numbers.
Math.Divide Divide numbers.
Math.Multiple Multiple numbers.
Math.Subtract Subtract numbers.
Move Moves files on the filesystem to a new location.
NDoc Runs NDoc to create documentation.
NUnit Runs tests using the NUnit.
RegistryRead Reads a value from the Registry.
RegistryWrite Writes a value to the Registry.
Script Executes code contained within the task.
ServiceController Task that can control a Windows service.
ServiceQuery Task that can determine the status of a service.
Sleep A task for sleeping for a specified period of time.
SqlExecute Executes a SQL command
SvnCheckout Checkout files from Subversion
SvnClient Subversion Client
SvnCommit Commit files to Subversion
SvnExport Export files from Subversion
SvnInfo Get Subversion information for a file or directory.
SvnUpdate Update files from Subversion
SvnVersion Get Subversion revision number of a local copy
TaskSchema Generates a XSD schema of the MSBuild tasks in an assembly.
Time Gets the current date and time.
Unzip Unzip a file to a target directory.
Version Increments a four-part version number stored in a text file
VssAdd Adds files to a Visual SourceSafe database.
VssCheckin Checks in files to a Visual SourceSafe database.
VssCheckout Checks out files from a Visual SourceSafe database.
VssClean Removes Visual SourceSafe binding information and status files from a Visual Studio solution tree.
VssDiff Generates a diff between two versions of an item in a Visual SourceSafe database.
VssGet Gets the latest version of a file or project from a Visual SourceSafe database.
VssHistory Generates an XML file containing the history of an item in a Visual SourceSafe database between two dates or labels.
VssLabel Labels an item in a Visual SourceSafe database.
VssUndoCheckout Cancels a checkout of an item from a Visual SourceSafe database.
WebDirectoryCreate Creates a new web directory on a local or remote machine.
WebDirectoryDelete Deletes a web directory on a local or remote machine
WebDownload Downloads a resource with the specified URI to a local file.
XmlRead Reads a value from a XML document using a XPath.
XmlWrite Updates a XML document using a XPath.
Xslt Merge and transform a set of xml files.
Zip Create a zip file with the files specified.

Join Project

Please join the MSBuild Community Tasks Project and help contribute in building the tasks.

Download The Latest Release

The latest binaries, source and installer for Windows can be found in this directory of the Tigris file-sharing area.

Create a Relative path code snippet

Here is a code snippet that is equivalent to the windows API PathRelativePathTo as native c#. The function creates a relative path from one file or folder to another.

public class PathUtil  
    /// <summary>  
    /// Creates a relative path from one file  
    /// or folder to another.  
    /// </summary>  
    /// <param name="fromDirectory">  
    /// Contains the directory that defines the   
    /// start of the relative path.  
    /// </param>  
    /// <param name="toPath">  
    /// Contains the path that defines the  
    /// endpoint of the relative path.  
    /// </param>  
    /// <returns>  
    /// The relative path from the start  
    /// directory to the end path.  
    /// </returns>  
    /// <exception cref="ArgumentNullException"></exception>  
    public static string RelativePathTo(  
        string fromDirectory, string toPath)  
        if (fromDirectory == null)  
            throw new ArgumentNullException("fromDirectory");  
        if (toPath == null)  
            throw new ArgumentNullException("toPath");  
        bool isRooted = Path.IsPathRooted(fromDirectory)  
            && Path.IsPathRooted(toPath);  
        if (isRooted)  
            bool isDifferentRoot = string.Compare(  
                Path.GetPathRoot(toPath), true) != 0;  
            if (isDifferentRoot)  
                return toPath;                           
        StringCollection relativePath = new StringCollection();  
        string[] fromDirectories = fromDirectory.Split(  
        string[] toDirectories = toPath.Split(  
        int length = Math.Min(  
        int lastCommonRoot = -1;  
        // find common root  
        for (int x = 0; x < length; x++)  
            if (string.Compare(fromDirectories[x],  
                toDirectories[x], true) != 0)  
            lastCommonRoot = x;  
        if (lastCommonRoot == -1)  
            return toPath;  
        // add relative folders in from path  
        for (int x = lastCommonRoot + 1; x < fromDirectories.Length; x++)  
            if (fromDirectories[x].Length > 0)  
        // add to folders to path  
        for (int x = lastCommonRoot + 1; x < toDirectories.Length; x++)  
        // create relative path  
        string[] relativeParts = new string[relativePath.Count];  
        relativePath.CopyTo(relativeParts, 0);  
        string newPath = string.Join(  
        return newPath;