Apply patch for AMQNET-556 from Stephane Ramet.  Thanks Stephane!
diff --git a/Apache.NMS.MSMQ.Test.nunit b/Apache.NMS.MSMQ.Test.nunit
index b321b9d..4dc9dc2 100644
--- a/Apache.NMS.MSMQ.Test.nunit
+++ b/Apache.NMS.MSMQ.Test.nunit
@@ -1,7 +1,7 @@
-<NUnitProject>

-  <Settings activeconfig="Default" />

-  <Config name="Default" binpathtype="Auto">

-    <assembly path="Apache.NMS.Test.dll" />

-    <assembly path="Apache.NMS.MSMQ.Test.dll" />

-  </Config>

+<NUnitProject>
+  <Settings activeconfig="Default" />
+  <Config name="Default" binpathtype="Auto">
+    <!--<assembly path="Apache.NMS.Test.dll" />-->
+    <assembly path="Apache.NMS.MSMQ.Test.dll" />
+  </Config>
 </NUnitProject>
\ No newline at end of file
diff --git a/msmqprovider-test.config b/msmqprovider-test.config
new file mode 100644
index 0000000..65e5dff
--- /dev/null
+++ b/msmqprovider-test.config
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+<configuration>
+	<testURI value="msmq://localhost">
+		<userName value="guest"/>
+		<passWord value="guest"/>
+		<defaultTestQueue value="queue://.\Private$\TestQ"/>
+		<defaultTestTopic value=""/>
+		<defaultTestQueue2 value="queue://.\Private$\TestQ2"/>
+		<defaultTestTopic2 value=""/>
+		<durableConsumerTestTopic value=""/>
+		<messageSelectorTestQueue value="queue://.\Private$\TestQ"/>
+		<messageSelectorTestTopic value=""/>
+		<deletionTestQueue value="queue://.\Private$\TestQ"/>
+		<deletionTestTopic value=""/>
+		<deletionTestTempQueue value=""/>
+		<deletionTestTempTopic value=""/>
+		<transactionTestQueue value="queue://.\Private$\TestQT"/>
+	</testURI>
+</configuration>
diff --git a/nant.build b/nant.build
index 0df9a29..67d0fa0 100644
--- a/nant.build
+++ b/nant.build
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0"?>
 <!--
     Licensed to the Apache Software Foundation (ASF) under one or more
     contributor license agreements.  See the NOTICE file distributed with
@@ -31,8 +31,6 @@
     <property name="nunit.dll" value="${basedir}/lib/NUnit/${current.build.framework}/nunit.framework.dll" dynamic="true" />
     <property name="Apache.NMS.dll" value="${basedir}/lib/Apache.NMS/${current.build.framework}/Apache.NMS.dll" dynamic="true" />
     <property name="Apache.NMS.pdb" value="${basedir}/lib/Apache.NMS/${current.build.framework}/Apache.NMS.pdb" dynamic="true" />
-    <property name="Apache.NMS.Test.dll" value="${basedir}/lib/Apache.NMS/${current.build.framework}//Apache.NMS.Test.dll" dynamic="true" />
-    <property name="Apache.NMS.Test.pdb" value="${basedir}/lib/Apache.NMS/${current.build.framework}/Apache.NMS.Test.pdb" dynamic="true" />
     <property name="NUnit.Projectfile" value="Apache.NMS.MSMQ.Test.nunit" />
 
     <!-- Skip certain frameworks, since MSMQ is not supported on those platforms. -->
@@ -77,7 +75,6 @@
             <include name="${current.build.framework.assembly.dir}/System.Xml.dll" />
             <include name="${current.build.framework.assembly.dir}/System.Messaging.dll" />
             <include name="${Apache.NMS.dll}" />
-            <include name="${Apache.NMS.Test.dll}" />
             <include name="${build.bin.dir}/${project.name}.dll" />
             <include name="${nunit.dll}" />
         </assemblyfileset>
@@ -88,8 +85,6 @@
             <include name="nmsprovider-*.config" />
             <include name="${Apache.NMS.dll}" />
             <include name="${Apache.NMS.pdb}" />
-            <include name="${Apache.NMS.Test.dll}" />
-            <include name="${Apache.NMS.Test.pdb}" />
             <include name="${nunit.dll}" />
             <include name="${NUnit.Projectfile}" />
         </fileset>
diff --git a/src/main/csharp/Connection.cs b/src/main/csharp/Connection.cs
index 9207708..5df73f4 100644
--- a/src/main/csharp/Connection.cs
+++ b/src/main/csharp/Connection.cs
@@ -16,6 +16,7 @@
  */
 
 using System;
+using System.Threading;
 
 namespace Apache.NMS.MSMQ
 {
@@ -26,21 +27,101 @@
     ///
     public class Connection : IConnection
     {
-        private AcknowledgementMode acknowledgementMode = AcknowledgementMode.AutoAcknowledge;
-        private IMessageConverter messageConverter = new DefaultMessageConverter();
+        #region Constructors
 
-        private IRedeliveryPolicy redeliveryPolicy;
-        private ConnectionMetaData metaData = null;
-        private bool connected;
-        private bool closed;
-        private string clientId;
+        public Connection()
+        {
+            // now lets send the connection and see if we get an ack/nak
+            // TODO: establish a connection
+        }
+
+        #endregion
+
+        #region Connection state
+
+        public enum ConnectionState
+        {
+            Created,
+            Connected,
+            Starting,
+            Started,
+            Stopping,
+            Stopped,
+            Closed
+        }
+
+        private ConnectionState state = ConnectionState.Created;
+
+        public class StateChangeEventArgs : EventArgs
+        {
+            public StateChangeEventArgs(ConnectionState originalState,
+                ConnectionState currentState)
+            {
+                this.originalState = originalState;
+                this.currentState = currentState;
+            }
+
+            private ConnectionState originalState;
+            public ConnectionState OriginalState
+            {
+                get { return originalState; }
+            }
+
+            private ConnectionState currentState;
+            public ConnectionState CurrentState
+            {
+                get { return currentState; }
+            }
+        }
+
+        public delegate void StateChangeEventHandler(object sender, StateChangeEventArgs e);
+
+        public event StateChangeEventHandler ConnectionStateChange;
+
+        private void ChangeState(ConnectionState newState)
+        {
+            if(ConnectionStateChange != null)
+            {
+                ConnectionStateChange(this, 
+                    new StateChangeEventArgs(this.state, newState));
+            }
+
+            this.state = newState;
+        }
+
+        private object stateLock = new object();
+
+        #endregion
+
+        #region Start & stop
 
         /// <summary>
         /// Starts message delivery for this connection.
         /// </summary>
         public void Start()
         {
-            CheckConnected();
+            lock(stateLock)
+            {
+                switch(state)
+                {
+                    case ConnectionState.Created:
+                    case ConnectionState.Connected:
+                    case ConnectionState.Stopped:
+                        ChangeState(ConnectionState.Starting);
+                        ChangeState(ConnectionState.Started);
+                        break;
+
+                    case ConnectionState.Stopping:
+                        throw new NMSException("Connection stopping");
+
+                    case ConnectionState.Closed:
+                        throw new NMSException("Connection closed");
+
+                    case ConnectionState.Starting:
+                    case ConnectionState.Started:
+                        break;
+                }
+            }
         }
 
         /// <summary>
@@ -49,7 +130,7 @@
         /// </summary>
         public bool IsStarted
         {
-            get { return true; }
+            get { return state == ConnectionState.Started; }
         }
 
         /// <summary>
@@ -57,9 +138,65 @@
         /// </summary>
         public void Stop()
         {
-            CheckConnected();
+            lock(stateLock)
+            {
+                switch(state)
+                {
+                    case ConnectionState.Started:
+                        ChangeState(ConnectionState.Stopping);
+                        ChangeState(ConnectionState.Stopped);
+                        break;
+
+                    case ConnectionState.Starting:
+                        throw new NMSException("Connection starting");
+
+                    case ConnectionState.Closed:
+                        throw new NMSException("Connection closed");
+
+                    case ConnectionState.Created:
+                    case ConnectionState.Connected:
+                    case ConnectionState.Stopping:
+                    case ConnectionState.Stopped:
+                        break;
+                }
+            }
         }
 
+        #endregion
+
+        #region Close & dispose
+
+        public void Close()
+        {
+            if(!IsClosed)
+            {
+                Stop();
+
+                state = ConnectionState.Closed;
+            }
+        }
+
+        public bool IsClosed
+        {
+            get { return state == ConnectionState.Closed; }
+        }
+
+        public void Dispose()
+        {
+            try
+            {
+                Close();
+            }
+            catch
+            {
+                state = ConnectionState.Closed;
+            }
+        }
+
+        #endregion
+
+        #region Create session
+
         /// <summary>
         /// Creates a new session to work on this connection
         /// </summary>
@@ -73,14 +210,16 @@
         /// </summary>
         public ISession CreateSession(AcknowledgementMode mode)
         {
-            CheckConnected();
+            if(IsClosed)
+            {
+                throw new NMSException("Connection closed");
+            }
             return new Session(this, mode);
         }
 
-        public void Dispose()
-        {
-            closed = true;
-        }
+        #endregion
+
+        #region Connection properties
 
         /// <summary>
         /// The default timeout for network requests.
@@ -91,24 +230,27 @@
             set { }
         }
 
+        private AcknowledgementMode acknowledgementMode = AcknowledgementMode.AutoAcknowledge;
         public AcknowledgementMode AcknowledgementMode
         {
             get { return acknowledgementMode; }
             set { acknowledgementMode = value; }
         }
 
+        private IMessageConverter messageConverter = new DefaultMessageConverter();
         public IMessageConverter MessageConverter
         {
             get { return messageConverter; }
             set { messageConverter = value; }
         }
 
+        private string clientId;
         public string ClientId
         {
             get { return clientId; }
             set
             {
-                if(connected)
+                if(state != ConnectionState.Created)
                 {
                     throw new NMSException("You cannot change the ClientId once the Connection is connected");
                 }
@@ -116,6 +258,7 @@
             }
         }
 
+        private IRedeliveryPolicy redeliveryPolicy;
         /// <summary>
         /// Get/or set the redelivery policy for this connection.
         /// </summary>
@@ -125,6 +268,19 @@
             set { this.redeliveryPolicy = value; }
         }
 
+        private ConnectionMetaData metaData = null;
+        /// <summary>
+        /// Gets the Meta Data for the NMS Connection instance.
+        /// </summary>
+        public IConnectionMetaData MetaData
+        {
+            get { return this.metaData ?? (this.metaData = new ConnectionMetaData()); }
+        }
+
+        #endregion
+
+        #region Transformer delegates
+
         private ConsumerTransformerDelegate consumerTransformer;
         public ConsumerTransformerDelegate ConsumerTransformer
         {
@@ -139,57 +295,18 @@
             set { this.producerTransformer = value; }
         }
 
-        /// <summary>
-        /// Gets the Meta Data for the NMS Connection instance.
-        /// </summary>
-        public IConnectionMetaData MetaData
-        {
-            get { return this.metaData ?? (this.metaData = new ConnectionMetaData()); }
-        }
+        #endregion
+
+        #region Exception & transport listeners
 
         /// <summary>
         /// A delegate that can receive transport level exceptions.
         /// </summary>
         public event ExceptionListener ExceptionListener;
 
-        /// <summary>
-        /// An asynchronous listener that is notified when a Fault tolerant connection
-        /// has been interrupted.
-        /// </summary>
-        public event ConnectionInterruptedListener ConnectionInterruptedListener;
-
-        /// <summary>
-        /// An asynchronous listener that is notified when a Fault tolerant connection
-        /// has been resumed.
-        /// </summary>
-        public event ConnectionResumedListener ConnectionResumedListener;
-
-        protected void CheckConnected()
-        {
-            if(closed)
-            {
-                throw new NMSException("Connection Closed");
-            }
-            if(!connected)
-            {
-                connected = true;
-                // now lets send the connection and see if we get an ack/nak
-                // TODO: establish a connection
-            }
-        }
-
-        public void Close()
-        {
-            Dispose();
-        }
-
-        public void PurgeTempDestinations()
-        {
-        }
-
         public void HandleException(Exception e)
         {
-            if(ExceptionListener != null && !this.closed)
+            if(ExceptionListener != null && !this.IsClosed)
             {
                 ExceptionListener(e);
             }
@@ -199,11 +316,17 @@
             }
         }
 
+        /// <summary>
+        /// An asynchronous listener that is notified when a Fault tolerant connection
+        /// has been interrupted.
+        /// </summary>
+        public event ConnectionInterruptedListener ConnectionInterruptedListener;
+
         public void HandleTransportInterrupted()
         {
             Tracer.Debug("Transport has been Interrupted.");
 
-            if(this.ConnectionInterruptedListener != null && !this.closed)
+            if(this.ConnectionInterruptedListener != null && !this.IsClosed)
             {
                 try
                 {
@@ -215,11 +338,17 @@
             }
         }
 
+        /// <summary>
+        /// An asynchronous listener that is notified when a Fault tolerant connection
+        /// has been resumed.
+        /// </summary>
+        public event ConnectionResumedListener ConnectionResumedListener;
+
         public void HandleTransportResumed()
         {
             Tracer.Debug("Transport has resumed normal operation.");
 
-            if(this.ConnectionResumedListener != null && !this.closed)
+            if(this.ConnectionResumedListener != null && !this.IsClosed)
             {
                 try
                 {
@@ -230,5 +359,11 @@
                 }
             }
         }
+
+        #endregion
+
+        public void PurgeTempDestinations()
+        {
+        }
     }
 }
diff --git a/src/main/csharp/ConnectionMetaData.cs b/src/main/csharp/ConnectionMetaData.cs
index 5a305c0..9bba3b6 100644
--- a/src/main/csharp/ConnectionMetaData.cs
+++ b/src/main/csharp/ConnectionMetaData.cs
@@ -1,107 +1,107 @@
-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-using System;

-using System.Reflection;

-

-namespace Apache.NMS.MSMQ

-{

-	/// <summary>

-	/// Implements the Connection Meta-Data feature for Apache.NMS.MSMQ

-	/// </summary>

-	public class ConnectionMetaData : IConnectionMetaData

-	{

-		private int nmsMajorVersion;

-		private int nmsMinorVersion;

-

-		private string nmsProviderName;

-		private string nmsVersion;

-

-		private int providerMajorVersion;

-		private int providerMinorVersion;

-		private string providerVersion;

-

-		private string[] nmsxProperties;

-

-		public ConnectionMetaData()

-		{

-			Assembly self = Assembly.GetExecutingAssembly();

-			AssemblyName asmName = self.GetName();

-

-			this.nmsProviderName = asmName.Name;

-			this.providerMajorVersion = asmName.Version.Major;

-			this.providerMinorVersion = asmName.Version.Minor;

-			this.providerVersion = asmName.Version.ToString();

-

-			this.nmsxProperties = new String[] { };

-

-			foreach(AssemblyName name in self.GetReferencedAssemblies())

-			{

-				if(0 == string.Compare(name.Name, "Apache.NMS", true))

-				{

-					this.nmsMajorVersion = name.Version.Major;

-					this.nmsMinorVersion = name.Version.Minor;

-					this.nmsVersion = name.Version.ToString();

-

-					return;

-				}

-			}

-

-			throw new NMSException("Could not find a reference to the Apache.NMS Assembly.");

-		}

-

-		public int NMSMajorVersion

-		{

-			get { return this.nmsMajorVersion; }

-		}

-

-		public int NMSMinorVersion

-		{

-			get { return this.nmsMinorVersion; }

-		}

-

-		public string NMSProviderName

-		{

-			get { return this.nmsProviderName; }

-		}

-

-		public string NMSVersion

-		{

-			get { return this.nmsVersion; }

-		}

-

-		public string[] NMSXPropertyNames

-		{

-			get { return this.nmsxProperties; }

-		}

-

-		public int ProviderMajorVersion

-		{

-			get { return this.providerMajorVersion; }

-		}

-

-		public int ProviderMinorVersion

-		{

-			get { return this.providerMinorVersion; }

-		}

-

-		public string ProviderVersion

-		{

-			get { return this.providerVersion; }

-		}

-	}

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Reflection;
+
+namespace Apache.NMS.MSMQ
+{
+	/// <summary>
+	/// Implements the Connection Meta-Data feature for Apache.NMS.MSMQ
+	/// </summary>
+	public class ConnectionMetaData : IConnectionMetaData
+	{
+		private int nmsMajorVersion;
+		private int nmsMinorVersion;
+
+		private string nmsProviderName;
+		private string nmsVersion;
+
+		private int providerMajorVersion;
+		private int providerMinorVersion;
+		private string providerVersion;
+
+		private string[] nmsxProperties;
+
+		public ConnectionMetaData()
+		{
+			Assembly self = Assembly.GetExecutingAssembly();
+			AssemblyName asmName = self.GetName();
+
+			this.nmsProviderName = asmName.Name;
+			this.providerMajorVersion = asmName.Version.Major;
+			this.providerMinorVersion = asmName.Version.Minor;
+			this.providerVersion = asmName.Version.ToString();
+
+			this.nmsxProperties = new String[] { };
+
+			foreach(AssemblyName name in self.GetReferencedAssemblies())
+			{
+				if(0 == string.Compare(name.Name, "Apache.NMS", true))
+				{
+					this.nmsMajorVersion = name.Version.Major;
+					this.nmsMinorVersion = name.Version.Minor;
+					this.nmsVersion = name.Version.ToString();
+
+					return;
+				}
+			}
+
+			throw new NMSException("Could not find a reference to the Apache.NMS Assembly.");
+		}
+
+		public int NMSMajorVersion
+		{
+			get { return this.nmsMajorVersion; }
+		}
+
+		public int NMSMinorVersion
+		{
+			get { return this.nmsMinorVersion; }
+		}
+
+		public string NMSProviderName
+		{
+			get { return this.nmsProviderName; }
+		}
+
+		public string NMSVersion
+		{
+			get { return this.nmsVersion; }
+		}
+
+		public string[] NMSXPropertyNames
+		{
+			get { return this.nmsxProperties; }
+		}
+
+		public int ProviderMajorVersion
+		{
+			get { return this.providerMajorVersion; }
+		}
+
+		public int ProviderMinorVersion
+		{
+			get { return this.providerMinorVersion; }
+		}
+
+		public string ProviderVersion
+		{
+			get { return this.providerVersion; }
+		}
+	}
+}
diff --git a/src/main/csharp/DefaultMessageConverter.cs b/src/main/csharp/DefaultMessageConverter.cs
index 83097fc..b726474 100644
--- a/src/main/csharp/DefaultMessageConverter.cs
+++ b/src/main/csharp/DefaultMessageConverter.cs
@@ -118,16 +118,16 @@
             // Populate property data
             foreach(object keyObject in message.Properties.Keys)
             {
-              string key = (keyObject as string);
-              object val = message.Properties.GetString(key);
-              if(!SetLabelAsNMSType && string.Compare(key, "Label", true) == 0 && val != null)
-              {
-				msmqMessage.Label = val.ToString();
-              }
-              else
-              {
-				propertyData[key] = val;
-              }
+                string key = (keyObject as string);
+                object val = message.Properties[key];
+                if(!SetLabelAsNMSType && string.Compare(key, "Label", true) == 0 && val != null)
+                {
+				    msmqMessage.Label = val.ToString();
+                }
+                else
+                {
+				    propertyData[key] = val;
+                }
             }
 
 			// Store the NMS property data in the extension area
@@ -418,6 +418,8 @@
 				result = baseMessage;
 			}
 
+            result.ReadOnlyBody = true;
+
 			return result;
 		}
 
@@ -442,6 +444,7 @@
 			else if(message is BytesMessage)
 			{
 				BytesMessage bytesMessage = message as BytesMessage;
+                bytesMessage.Reset();
 				answer.BodyStream.Write(bytesMessage.Content, 0, bytesMessage.Content.Length);
 				answer.AppSpecific = (int) NMSMessageType.BytesMessage;
 			}
@@ -604,12 +607,14 @@
         /// <result>MSMQ queue.</result>
 		public MessageQueue ToMsmqDestination(IDestination destination)
 		{
-			if(null == destination)
+            Queue queue = destination as Queue;
+
+			if(destination == null)
 			{
 				return null;
 			}
 
-			return new MessageQueue((destination as Destination).Path);
+			return queue.MSMQMessageQueue;
 		}
 
         /// <summary>
@@ -625,7 +630,7 @@
 				return null;
 			}
 
-			return new Queue(destinationQueue.Path);
+			return new Queue(destinationQueue);
 		}
 
         #endregion
diff --git a/src/main/csharp/IMessageConverterEx.cs b/src/main/csharp/IMessageConverterEx.cs
index 92be928..fcd1354 100644
--- a/src/main/csharp/IMessageConverterEx.cs
+++ b/src/main/csharp/IMessageConverterEx.cs
@@ -1,44 +1,44 @@
-using System.Messaging;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ

-{

-    /// <summary>

-    /// Extended IMessageConverter interface supporting new methods for

-    /// optimizing message selection through "selectors".

-    /// The original IMessageConverter is maintained for compatibility

-    /// reasons with existing clients implementing it.

-    /// </summary>

-	public interface IMessageConverterEx : IMessageConverter

-	{

-        /// <summary>

-        /// Converts the specified MSMQ message to an equivalent NMS message.

-        /// </summary>

-        /// <param name="message">MSMQ message to be converted.</param>

-        /// <param name="convertBody">true if message body should be converted.</param>

-        /// <result>Converted NMS message.</result>

-		IMessage ToNmsMessage(Message message, bool convertBody);

-

-        /// <summary>

-        /// Converts an MSMQ message body to the equivalent NMS message body.

-        /// </summary>

-        /// <param name="message">Source MSMQ message.</param>

-        /// <param name="answer">Target NMS message.</param>

-		void ConvertMessageBodyToNMS(Message message, IMessage answer);

-	}

-}

+using System.Messaging;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ
+{
+    /// <summary>
+    /// Extended IMessageConverter interface supporting new methods for
+    /// optimizing message selection through "selectors".
+    /// The original IMessageConverter is maintained for compatibility
+    /// reasons with existing clients implementing it.
+    /// </summary>
+	public interface IMessageConverterEx : IMessageConverter
+	{
+        /// <summary>
+        /// Converts the specified MSMQ message to an equivalent NMS message.
+        /// </summary>
+        /// <param name="message">MSMQ message to be converted.</param>
+        /// <param name="convertBody">true if message body should be converted.</param>
+        /// <result>Converted NMS message.</result>
+		IMessage ToNmsMessage(Message message, bool convertBody);
+
+        /// <summary>
+        /// Converts an MSMQ message body to the equivalent NMS message body.
+        /// </summary>
+        /// <param name="message">Source MSMQ message.</param>
+        /// <param name="answer">Target NMS message.</param>
+		void ConvertMessageBodyToNMS(Message message, IMessage answer);
+	}
+}
diff --git a/src/main/csharp/MessageConsumer.cs b/src/main/csharp/MessageConsumer.cs
index eaaed5c..c69c6f5 100644
--- a/src/main/csharp/MessageConsumer.cs
+++ b/src/main/csharp/MessageConsumer.cs
@@ -32,9 +32,6 @@
         private readonly Session session;
         private readonly AcknowledgementMode acknowledgementMode;
         private MessageQueue messageQueue;
-        private Thread asyncDeliveryThread = null;
-        private AutoResetEvent pause = new AutoResetEvent(false);
-        private Atomic<bool> asyncDelivery = new Atomic<bool>(false);
 
         private ConsumerTransformerDelegate consumerTransformer;
         public ConsumerTransformerDelegate ConsumerTransformer
@@ -81,6 +78,8 @@
                 messageQueue, session.MessageConverter, selector);
         }
 
+        #region Asynchronous delivery
+
         private int listenerCount = 0;
         private event MessageListener listener;
         public event MessageListener Listener
@@ -89,7 +88,13 @@
             {
                 listener += value;
                 listenerCount++;
-                StartAsyncDelivery();
+
+                session.Connection.ConnectionStateChange += OnConnectionStateChange;
+
+                if(session.Connection.IsStarted)
+                {
+                    StartAsyncDelivery();
+                }
             }
 
             remove
@@ -100,13 +105,112 @@
                     listenerCount--;
                 }
 
-                if(0 == listenerCount)
+                if(listenerCount == 0)
+                {
+                    session.Connection.ConnectionStateChange -= OnConnectionStateChange;
+
+                    StopAsyncDelivery();
+                }
+            }
+        }
+
+        private void OnConnectionStateChange(object sender, Connection.StateChangeEventArgs e)
+        {
+            if(e.CurrentState == Connection.ConnectionState.Starting)
+            {
+                if(listenerCount > 0)
+                {
+                    StartAsyncDelivery();
+                }
+            }
+            else if(e.CurrentState == Connection.ConnectionState.Stopping)
+            {
+                if(listenerCount > 0)
                 {
                     StopAsyncDelivery();
                 }
             }
         }
 
+        private Thread asyncDeliveryThread = null;
+        private Atomic<bool> asyncDelivery = new Atomic<bool>(false);
+        TimeSpan dispatchingTimeout = new TimeSpan(5000);
+
+        protected virtual void StartAsyncDelivery()
+        {
+            if(asyncDelivery.CompareAndSet(false, true))
+            {
+                asyncDeliveryThread = new Thread(new ThreadStart(DispatchLoop));
+                asyncDeliveryThread.Name = "Message Consumer Dispatch: " + messageQueue.QueueName;
+                asyncDeliveryThread.IsBackground = true;
+                asyncDeliveryThread.Start();
+            }
+        }
+
+        protected virtual void DispatchLoop()
+        {
+            Tracer.Info("Starting dispatcher thread consumer: " + this);
+            while(asyncDelivery.Value)
+            {
+                try
+                {
+                    IMessage message = Receive(dispatchingTimeout);
+                    if(asyncDelivery.Value && message != null)
+                    {
+                        try
+                        {
+                            listener(message);
+                        }
+                        catch(Exception e)
+                        {
+                            HandleAsyncException(e);
+                        }
+                    }
+                }
+                catch(ThreadAbortException ex)
+                {
+                    Tracer.InfoFormat("Thread abort received in thread: {0} : {1}", this, ex.Message);
+
+                    break;
+                }
+                catch(Exception ex)
+                {
+                    Tracer.ErrorFormat("Exception while receiving message in thread: {0} : {1}", this, ex.Message);
+                }
+            }
+            Tracer.Info("Stopping dispatcher thread consumer: " + this);
+        }
+
+        protected virtual void StopAsyncDelivery()
+        {
+            if(asyncDelivery.CompareAndSet(true, false))
+            {
+                if(null != asyncDeliveryThread)
+                {
+                    // Thread.Interrupt and Thread.Abort do not interrupt Receive
+                    // instructions. Attempting to abort the thread and joining
+                    // will result in a phantom backgroud thread, which may
+                    // ultimately consume a message before actually stopping.
+
+                    Tracer.Info("Waiting for thread to complete aborting.");
+                    asyncDeliveryThread.Join(dispatchingTimeout);
+
+                    asyncDeliveryThread = null;
+                    Tracer.Info("Async delivery thread stopped.");
+                }
+            }
+        }
+
+
+        protected virtual void HandleAsyncException(Exception e)
+        {
+            session.Connection.HandleException(e);
+        }
+
+        #endregion
+
+        #region Receive (synchronous)
+
         public IMessage Receive()
         {
             IMessage nmsMessage = null;
@@ -126,7 +230,17 @@
 
             if(messageQueue != null)
             {
-                nmsMessage = reader.Receive(timeout);
+                try
+                {
+                    nmsMessage = reader.Receive(timeout);
+                }
+                catch(MessageQueueException ex)
+                {
+                    if(ex.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
+                    {
+                        throw ex;
+                    }
+                }
                 nmsMessage = TransformMessage(nmsMessage);
             }
 
@@ -135,17 +249,13 @@
 
         public IMessage ReceiveNoWait()
         {
-            IMessage nmsMessage = null;
-
-            if(messageQueue != null)
-            {
-                nmsMessage = reader.Receive(zeroTimeout);
-                nmsMessage = TransformMessage(nmsMessage);
-            }
-
-            return nmsMessage;
+            return Receive(zeroTimeout);
         }
 
+        #endregion
+
+        #region Close & dispose
+
         public void Dispose()
         {
             Close();
@@ -153,7 +263,13 @@
 
         public void Close()
         {
-            StopAsyncDelivery();
+            if(listenerCount > 0)
+            {
+                session.Connection.ConnectionStateChange -= OnConnectionStateChange;
+
+                StopAsyncDelivery();
+            }
+
             if(messageQueue != null)
             {
                 messageQueue.Dispose();
@@ -161,74 +277,7 @@
             }
         }
 
-        protected virtual void StopAsyncDelivery()
-        {
-            if(asyncDelivery.CompareAndSet(true, false))
-            {
-                if(null != asyncDeliveryThread)
-                {
-                    Tracer.Info("Stopping async delivery thread.");
-                    pause.Set();
-                    if(!asyncDeliveryThread.Join(10000))
-                    {
-                        Tracer.Info("Aborting async delivery thread.");
-                        asyncDeliveryThread.Abort();
-                    }
-
-                    asyncDeliveryThread = null;
-                    Tracer.Info("Async delivery thread stopped.");
-                }
-            }
-        }
-
-        protected virtual void StartAsyncDelivery()
-        {
-            if(asyncDelivery.CompareAndSet(false, true))
-            {
-                asyncDeliveryThread = new Thread(new ThreadStart(DispatchLoop));
-                asyncDeliveryThread.Name = "Message Consumer Dispatch: " + messageQueue.QueueName;
-                asyncDeliveryThread.IsBackground = true;
-                asyncDeliveryThread.Start();
-            }
-        }
-
-        protected virtual void DispatchLoop()
-        {
-            Tracer.Info("Starting dispatcher thread consumer: " + this);
-            while(asyncDelivery.Value)
-            {
-                try
-                {
-                    IMessage message = Receive();
-                    if(asyncDelivery.Value && message != null)
-                    {
-                        try
-                        {
-                            listener(message);
-                        }
-                        catch(Exception e)
-                        {
-                            HandleAsyncException(e);
-                        }
-                    }
-                }
-                catch(ThreadAbortException ex)
-                {
-                    Tracer.InfoFormat("Thread abort received in thread: {0} : {1}", this, ex.Message);
-                    break;
-                }
-                catch(Exception ex)
-                {
-                    Tracer.ErrorFormat("Exception while receiving message in thread: {0} : {1}", this, ex.Message);
-                }
-            }
-            Tracer.Info("Stopping dispatcher thread consumer: " + this);
-        }
-
-        protected virtual void HandleAsyncException(Exception e)
-        {
-            session.Connection.HandleException(e);
-        }
+        #endregion
 
         protected virtual IMessage TransformMessage(IMessage message)
         {
diff --git a/src/main/csharp/MessageProducer.cs b/src/main/csharp/MessageProducer.cs
index 8690fc4..4a0bed4 100644
--- a/src/main/csharp/MessageProducer.cs
+++ b/src/main/csharp/MessageProducer.cs
@@ -50,41 +50,47 @@
             this.destination = destination;
             if(destination != null)
             {
-                messageQueue = openMessageQueue(destination);
+                messageQueue = OpenMessageQueue(destination);
             }
         }
 
-        private MessageQueue openMessageQueue(Destination dest)
+        private MessageQueue OpenMessageQueue(Destination dest)
         {
-            MessageQueue rc = null;
-            try
+            Queue queue = dest as Queue;
+
+            MessageQueue mq = queue.MSMQMessageQueue;
+
+            if(mq == null)
             {
-                if(!MessageQueue.Exists(dest.Path))
+                try
                 {
-                    // create the new message queue and make it transactional
-                    rc = MessageQueue.Create(dest.Path, session.Transacted);
-                    this.destination.Path = rc.Path;
-                }
-                else
-                {
-                    rc = new MessageQueue(dest.Path);
-                    this.destination.Path = rc.Path;
-                    if(!rc.CanWrite)
+                    if(!Queue.Exists(dest.Path))
                     {
-                        throw new NMSSecurityException("Do not have write access to: " + dest);
+                        // create the new message queue and make it transactional
+                        mq = MessageQueue.Create(dest.Path, session.Transacted);
+                        this.destination = new Queue(mq);
+                    }
+                    else
+                    {
+                        mq = new MessageQueue(dest.Path);
+                        this.destination = new Queue(mq);
+                        if(!mq.CanWrite)
+                        {
+                            throw new NMSSecurityException("Do not have write access to: " + dest);
+                        }
                     }
                 }
-            }
-            catch(Exception e)
-            {
-                if(rc != null)
+                catch(Exception e)
                 {
-                    rc.Dispose();
+                    if(mq != null)
+                    {
+                        mq.Dispose();
+                    }
+                
+                    throw new NMSException(e.Message + ": " + dest, e);
                 }
-
-                throw new NMSException(e.Message + ": " + dest, e);
             }
-            return rc;
+            return mq;
         }
 
         public void Send(IMessage message)
@@ -111,18 +117,28 @@
                 // Locate the MSMQ Queue we will be sending to
                 if(messageQueue != null)
                 {
+                    if(destination == null)
+                    {
+                        throw new InvalidDestinationException("This producer can only be used to send to: " + destination);
+                    }
+
                     if(destination.Equals(this.destination))
                     {
                         mq = messageQueue;
                     }
                     else
                     {
-                        throw new NMSException("This producer can only be used to send to: " + destination);
+                        throw new NotSupportedException("This producer can only be used to send to: " + destination);
                     }
                 }
                 else
                 {
-                    mq = openMessageQueue((Destination) destination);
+                    if(destination == null)
+                    {
+                        throw new NotSupportedException();
+                    }
+
+                    mq = OpenMessageQueue((Destination) destination);
                 }
 
                 if(this.ProducerTransformer != null)
@@ -147,7 +163,7 @@
                     // TODO: message.NMSMessageId =
                 }
 
-                // Convert the Mesasge into a MSMQ message
+                // Convert the Message into a MSMQ message
                 Message msg = session.MessageConverter.ToMsmqMessage(message);
 
                 if(mq.Transactional)
@@ -179,6 +195,11 @@
                     mq.Send(msg);
                 }
 
+                message.NMSMessageId = msg.Id;
+                if(message.NMSCorrelationID == null)
+                {
+                    message.NMSCorrelationID = msg.CorrelationId;
+                }
             }
             finally
             {
diff --git a/src/main/csharp/Queue.cs b/src/main/csharp/Queue.cs
index 30efcd9..4444a1b 100644
--- a/src/main/csharp/Queue.cs
+++ b/src/main/csharp/Queue.cs
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 using System;
+using System.Messaging;
 
 namespace Apache.NMS.MSMQ
 {
@@ -24,17 +25,69 @@
 	/// </summary>
 	public class Queue : Destination, IQueue
 	{
-
 		public Queue()
 			: base()
 		{
 		}
 
+		public Queue(MessageQueue messageQueue)
+			: base()
+		{
+			this.messageQueue = messageQueue;
+            Path = messageQueue.Path;
+		}
+
 		public Queue(String name)
 			: base(name)
 		{
+			if(string.IsNullOrEmpty(name))
+			{
+				messageQueue = null;
+			}
+            else
+            {
+                try
+                {
+                    messageQueue = new MessageQueue(name);
+                }
+                catch(Exception /*ex*/)
+                {
+                    // Excerpt from Microsoft documentation for MessageQueue.Exists :
+                    // (@https://msdn.microsoft.com/fr-fr/library/system.messaging.messagequeue.exists(v=vs.110).aspx)
+                    // Exists(String) is an expensive operation. Use it only when it is necessary within the application.
+                    // ---
+                    // Therefore, we won't check for existence of the queue before attempting to access it.
+
+                    //if(!Exists(name))
+                    //{
+                        // Excerpt from the Oracle JMS JavaDoc for Session.createQueue :
+                        // (@https://docs.oracle.com/javaee/7/api/javax/jms/Session.html#createQueue-java.lang.String-)
+                        // Note that this method simply creates an object that encapsulates the name of a queue. It does
+                        // not create the physical queue in the JMS provider. JMS does not provide a method to create the
+                        // physical queue, since this would be specific to a given JMS provider. Creating a physical queue
+                        // is provider-specific and is typically an administrative task performed by an administrator,
+                        // though some providers may create them automatically when needed. The one exception to this is
+                        // the creation of a temporary queue, which is done using the createTemporaryQueue method.
+                        // ---
+                        // Therefore, we should throw an NMSException if the queue does not exist.
+                        // ---
+                        // BUT, to keep it compatible with the initial implementation of MessageProducer, which attempts
+                        // to create non pre-existing queues, we keep it silent..
+
+                        // throw new NMSException("Message queue \"" + name + "\" does not exist", ex);
+                    //}
+
+                    // throw new NMSException("Cannot access message queue \"" + name + "\"", ex);
+                }
+            }
 		}
 
+        private MessageQueue messageQueue;
+        public MessageQueue MSMQMessageQueue
+        {
+            get { return messageQueue; }
+        }
+
 		override public DestinationType DestinationType
 		{
 			get
@@ -54,7 +107,25 @@
 			return new Queue(name);
 		}
 
+        public static bool Exists(string name)
+        {
+            try
+            {
+                return MessageQueue.Exists(name);
+            }
+            catch(InvalidOperationException)
+            {
+                // Excerpt from Microsoft documentation for MessageQueue.Exists :
+                // (@https://msdn.microsoft.com/fr-fr/library/system.messaging.messagequeue.exists(v=vs.110).aspx)
+                // InvalidOperationException: The application used format name syntax when verifying queue existence. 
+                // ---
+                // The Exists(String) method does not support the FormatName prefix.
+                // No method exists to determine whether a queue with a specified format name exists.
 
+                // We'll assume the queue exists at this point
+                return true;
+            }
+        }
 	}
 }
 
diff --git a/src/main/csharp/QueueBrowser.cs b/src/main/csharp/QueueBrowser.cs
index 3ff795d..9ccc2f9 100644
--- a/src/main/csharp/QueueBrowser.cs
+++ b/src/main/csharp/QueueBrowser.cs
@@ -1,164 +1,172 @@
-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-using System;

-using System.Collections;

-using System.Messaging;

-using Apache.NMS;

-using Apache.NMS.Util;

-using Apache.NMS.MSMQ.Readers;

-

-namespace Apache.NMS.MSMQ

-{

-	public class QueueBrowser : Apache.NMS.IQueueBrowser

-	{

-		private bool closed = false;

-		private bool disposed = false;

-

-        private readonly Session session;

-        private MessageQueue messageQueue;

-

-        private string selector;

-

-        private IMessageReader reader;

-        

-		public QueueBrowser(Session session, MessageQueue messageQueue)

-            : this(session, messageQueue, null)

-		{

-		}

-

-		public QueueBrowser(Session session, MessageQueue messageQueue,

-            string selector)

-		{

-            this.session = session;

-            this.messageQueue = messageQueue;

-            if(null != this.messageQueue)

-            {

-                this.messageQueue.MessageReadPropertyFilter.SetAll();

-            }

-

-            reader = MessageReaderUtil.CreateMessageReader(

-                messageQueue, session.MessageConverter, selector);

-		}

-

-		~QueueBrowser()

-		{

-			Dispose(false);

-		}

-

-		#region IDisposable Members

-

-		///<summary>

-		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

-		///</summary>

-		public void Dispose()

-		{

-			Dispose(true);

-			GC.SuppressFinalize(this);

-		}

-

-		protected void Dispose(bool disposing)

-		{

-			if(disposed)

-			{

-				return;

-			}

-

-			if(disposing)

-			{

-				// Dispose managed code here.

-			}

-

-			try

-			{

-				Close();

-			}

-			catch

-			{

-				// Ignore errors.

-			}

-

-			disposed = true;

-		}

-

-		#endregion

-

-		public void  Close()

-		{

-            if(messageQueue != null)

-            {

-                messageQueue.Dispose();

-                messageQueue = null;

-            }

-			closed = true;

-		}

-

-		public string MessageSelector

-		{

-			get { return selector; }

-		}

-

-		public IQueue Queue

-		{

-			get { return new Queue(this.messageQueue.Path); }

-		}

-

-		internal class Enumerator : IEnumerator

-		{

-			private readonly Session session;

-			private readonly MessageEnumerator innerEnumerator;

-            private readonly IMessageReader reader;

-

-			public Enumerator(Session session, MessageQueue messageQueue,

-                IMessageReader reader)

-			{

-				this.session = session;

-				this.innerEnumerator = messageQueue.GetMessageEnumerator2();

-                this.reader = reader;

-			}

-

-			public object Current

-			{

-				get

-				{

-					return this.session.MessageConverter.ToNmsMessage(this.innerEnumerator.Current);

-				}

-			}

-

-			public bool MoveNext()

-			{

-                while(this.innerEnumerator.MoveNext())

-                {

-				    if(reader.Matches(this.innerEnumerator.Current))

-                    {

-                        return true;

-                    }

-                }

-                return false;

-			}

-

-			public void Reset()

-			{

-				this.innerEnumerator.Reset();

-			}

-		}

-

-		public IEnumerator GetEnumerator()

-		{

-			return new Enumerator(this.session, this.messageQueue, this.reader);

-		}

-	}

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using System.Messaging;
+using Apache.NMS;
+using Apache.NMS.Util;
+using Apache.NMS.MSMQ.Readers;
+
+namespace Apache.NMS.MSMQ
+{
+	public class QueueBrowser : Apache.NMS.IQueueBrowser
+	{
+		private bool disposed = false;
+
+        private readonly Session session;
+        private MessageQueue messageQueue;
+
+        private string selector;
+
+        private IMessageReader reader;
+        
+		public QueueBrowser(Session session, MessageQueue messageQueue)
+            : this(session, messageQueue, null)
+		{
+		}
+
+		public QueueBrowser(Session session, MessageQueue messageQueue,
+            string selector)
+		{
+            this.session = session;
+            this.messageQueue = messageQueue;
+            if(null != this.messageQueue)
+            {
+                this.messageQueue.MessageReadPropertyFilter.SetAll();
+            }
+            this.selector = selector;
+
+            reader = MessageReaderUtil.CreateMessageReader(
+                messageQueue, session.MessageConverter, selector);
+		}
+
+		~QueueBrowser()
+		{
+			Dispose(false);
+		}
+
+		#region IDisposable Members
+
+		///<summary>
+		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+		///</summary>
+		public void Dispose()
+		{
+			Dispose(true);
+			GC.SuppressFinalize(this);
+		}
+
+		protected void Dispose(bool disposing)
+		{
+			if(disposed)
+			{
+				return;
+			}
+
+			if(disposing)
+			{
+				// Dispose managed code here.
+			}
+
+			try
+			{
+				Close();
+			}
+			catch
+			{
+				// Ignore errors.
+			}
+
+			disposed = true;
+		}
+
+		#endregion
+
+		public void  Close()
+		{
+            if(messageQueue != null)
+            {
+                messageQueue.Dispose();
+                messageQueue = null;
+            }
+		}
+
+		public string MessageSelector
+		{
+			get { return selector; }
+		}
+
+		public IQueue Queue
+		{
+			get { return new Queue(this.messageQueue.Path); }
+		}
+
+		internal class Enumerator : IEnumerator, IDisposable
+		{
+			private Session session;
+			private MessageEnumerator innerEnumerator;
+            private IMessageReader reader;
+
+			public Enumerator(Session session, MessageQueue messageQueue,
+                IMessageReader reader)
+			{
+				this.session = session;
+				this.innerEnumerator = messageQueue.GetMessageEnumerator2();
+                this.reader = reader;
+			}
+
+			public object Current
+			{
+				get
+				{
+					return this.session.MessageConverter.ToNmsMessage(this.innerEnumerator.Current);
+				}
+			}
+
+			public bool MoveNext()
+			{
+                while(this.innerEnumerator.MoveNext())
+                {
+				    if(reader.Matches(this.innerEnumerator.Current))
+                    {
+                        return true;
+                    }
+                }
+                return false;
+			}
+
+			public void Reset()
+			{
+				this.innerEnumerator.Reset();
+			}
+
+            public void Dispose()
+            {
+                if(innerEnumerator != null)
+                {
+                    innerEnumerator.Close();
+                    innerEnumerator = null;
+                }
+            }
+		}
+
+		public IEnumerator GetEnumerator()
+		{
+			return new Enumerator(this.session, this.messageQueue, this.reader);
+		}
+	}
+}
diff --git a/src/main/csharp/Readers/AbstractMessageReader.cs b/src/main/csharp/Readers/AbstractMessageReader.cs
index 7874696..dcb217d 100644
--- a/src/main/csharp/Readers/AbstractMessageReader.cs
+++ b/src/main/csharp/Readers/AbstractMessageReader.cs
@@ -1,126 +1,126 @@
-using System;

-using System.Messaging;

-using Apache.NMS.MSMQ;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ.Readers

-{

-    /// <summary>

-    /// Abstract MSMQ message reader. Derived classes support various

-    /// message filtering methods.

-    /// </summary>

-	public abstract class AbstractMessageReader : IMessageReader

-	{

-        protected MessageQueue messageQueue;

-        protected IMessageConverter messageConverter;

-        protected IMessageConverterEx messageConverterEx;

-

-        /// <summary>

-        /// Constructor.

-        /// </summary>

-        /// <param name="messageQueue">The MSMQ message queue from which

-        /// messages will be read.</param>

-        /// <param name="messageConverter">A message converter for mapping

-        /// MSMQ messages to NMS messages.</param>

-        public AbstractMessageReader(MessageQueue messageQueue,

-            IMessageConverter messageConverter)

-        {

-            this.messageQueue = messageQueue;

-

-            this.messageConverter = messageConverter;

-            this.messageConverterEx = (messageConverter as IMessageConverterEx);

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available.

-        /// </summary>

-        /// <returns>Peeked message.</returns>

-        public abstract IMessage Peek();

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available or the specified time-out occurs.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Peeked message.</returns>

-        public abstract IMessage Peek(TimeSpan timeSpan);

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by

-        /// the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <returns>Received message.</returns>

-        public abstract IMessage Receive();

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by the

-        /// MessageQueue matching the selection criteria, and waits until either

-        /// a message is available in the queue, or the time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Received message.</returns>

-        public abstract IMessage Receive(TimeSpan timeSpan);

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public abstract IMessage Receive(MessageQueueTransaction transaction);

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria,

-        /// and waits until either a message is available in the queue, or the

-        /// time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public abstract IMessage Receive(TimeSpan timeSpan,

-            MessageQueueTransaction transaction);

-

-        /// <summary>

-        /// Checks if an MSMQ message matches the selection criteria.

-        /// </summary>

-        /// <param name="message">MSMQ message.</param>

-        /// <return>true if the message matches the selection criteria.</return>

-        public abstract bool Matches(Message message);

-

-        /// <summary>

-        /// Converts an MSMQ message to an NMS message, using the converter

-        /// specified at construction time.

-        /// </summary>

-        /// <param name="message">MSMQ message.</param>

-        /// <return>NMS message.</return>

-        protected IMessage Convert(Message message)

-        {

-            return message == null ? null : messageConverter.ToNmsMessage(message);

-        }

-	}

-}

+using System;
+using System.Messaging;
+using Apache.NMS.MSMQ;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ.Readers
+{
+    /// <summary>
+    /// Abstract MSMQ message reader. Derived classes support various
+    /// message filtering methods.
+    /// </summary>
+	public abstract class AbstractMessageReader : IMessageReader
+	{
+        protected MessageQueue messageQueue;
+        protected IMessageConverter messageConverter;
+        protected IMessageConverterEx messageConverterEx;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="messageQueue">The MSMQ message queue from which
+        /// messages will be read.</param>
+        /// <param name="messageConverter">A message converter for mapping
+        /// MSMQ messages to NMS messages.</param>
+        public AbstractMessageReader(MessageQueue messageQueue,
+            IMessageConverter messageConverter)
+        {
+            this.messageQueue = messageQueue;
+
+            this.messageConverter = messageConverter;
+            this.messageConverterEx = (messageConverter as IMessageConverterEx);
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available.
+        /// </summary>
+        /// <returns>Peeked message.</returns>
+        public abstract IMessage Peek();
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available or the specified time-out occurs.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Peeked message.</returns>
+        public abstract IMessage Peek(TimeSpan timeSpan);
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by
+        /// the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <returns>Received message.</returns>
+        public abstract IMessage Receive();
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by the
+        /// MessageQueue matching the selection criteria, and waits until either
+        /// a message is available in the queue, or the time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Received message.</returns>
+        public abstract IMessage Receive(TimeSpan timeSpan);
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public abstract IMessage Receive(MessageQueueTransaction transaction);
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria,
+        /// and waits until either a message is available in the queue, or the
+        /// time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public abstract IMessage Receive(TimeSpan timeSpan,
+            MessageQueueTransaction transaction);
+
+        /// <summary>
+        /// Checks if an MSMQ message matches the selection criteria.
+        /// </summary>
+        /// <param name="message">MSMQ message.</param>
+        /// <return>true if the message matches the selection criteria.</return>
+        public abstract bool Matches(Message message);
+
+        /// <summary>
+        /// Converts an MSMQ message to an NMS message, using the converter
+        /// specified at construction time.
+        /// </summary>
+        /// <param name="message">MSMQ message.</param>
+        /// <return>NMS message.</return>
+        protected IMessage Convert(Message message)
+        {
+            return message == null ? null : messageConverter.ToNmsMessage(message);
+        }
+	}
+}
diff --git a/src/main/csharp/Readers/ByCorrelationIdMessageReader.cs b/src/main/csharp/Readers/ByCorrelationIdMessageReader.cs
index fad3d1a..bc8d832 100644
--- a/src/main/csharp/Readers/ByCorrelationIdMessageReader.cs
+++ b/src/main/csharp/Readers/ByCorrelationIdMessageReader.cs
@@ -1,139 +1,139 @@
-using System;

-using System.Messaging;

-using Apache.NMS.MSMQ;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ.Readers

-{

-    /// <summary>

-    /// MSMQ message reader, returning messages matching the specified

-    /// message identifier.

-    /// </summary>

-	public class ByCorrelationIdMessageReader : AbstractMessageReader

-	{

-        private string correlationId;

-

-        /// <summary>

-        /// Constructor.

-        /// </summary>

-        /// <param name="messageQueue">The MSMQ message queue from which

-        /// messages will be read.</param>

-        /// <param name="messageConverter">A message converter for mapping

-        /// MSMQ messages to NMS messages.</param>

-        /// <param name="correlationId">The correlation identifier of messages

-        /// to be read.</param>

-        public ByCorrelationIdMessageReader(MessageQueue messageQueue,

-            IMessageConverter messageConverter, string correlationId)

-            : base(messageQueue, messageConverter)

-        {

-            this.correlationId = correlationId;

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available.

-        /// </summary>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek()

-        {

-            return Convert(messageQueue.PeekByCorrelationId(correlationId));

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available or the specified time-out occurs.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek(TimeSpan timeSpan)

-        {

-            return Convert(messageQueue.PeekByCorrelationId(correlationId,

-                timeSpan));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by

-        /// the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive()

-        {

-            return Convert(messageQueue.ReceiveByCorrelationId(correlationId));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by the

-        /// MessageQueue matching the selection criteria, and waits until either

-        /// a message is available in the queue, or the time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan)

-        {

-            return Convert(messageQueue.ReceiveByCorrelationId(correlationId,

-                timeSpan));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(MessageQueueTransaction transaction)

-        {

-            return Convert(messageQueue.ReceiveByCorrelationId(correlationId,

-                transaction));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria,

-        /// and waits until either a message is available in the queue, or the

-        /// time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan,

-            MessageQueueTransaction transaction)

-        {

-            return Convert(messageQueue.ReceiveByCorrelationId(correlationId,

-                timeSpan, transaction));

-        }

-

-        /// <summary>

-        /// Checks if an MSMQ message matches the selection criteria.

-        /// </summary>

-        /// <param name="message">MSMQ message.</param>

-        /// <return>true if the message matches the selection criteria.</return>

-        public override bool Matches(Message message)

-        {

-            // NB: case-sensitive match

-            return message.CorrelationId == correlationId;

-        }

-	}

-}

+using System;
+using System.Messaging;
+using Apache.NMS.MSMQ;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ.Readers
+{
+    /// <summary>
+    /// MSMQ message reader, returning messages matching the specified
+    /// message identifier.
+    /// </summary>
+	public class ByCorrelationIdMessageReader : AbstractMessageReader
+	{
+        private string correlationId;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="messageQueue">The MSMQ message queue from which
+        /// messages will be read.</param>
+        /// <param name="messageConverter">A message converter for mapping
+        /// MSMQ messages to NMS messages.</param>
+        /// <param name="correlationId">The correlation identifier of messages
+        /// to be read.</param>
+        public ByCorrelationIdMessageReader(MessageQueue messageQueue,
+            IMessageConverter messageConverter, string correlationId)
+            : base(messageQueue, messageConverter)
+        {
+            this.correlationId = correlationId;
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available.
+        /// </summary>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek()
+        {
+            return Convert(messageQueue.PeekByCorrelationId(correlationId));
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available or the specified time-out occurs.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek(TimeSpan timeSpan)
+        {
+            return Convert(messageQueue.PeekByCorrelationId(correlationId,
+                timeSpan));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by
+        /// the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive()
+        {
+            return Convert(messageQueue.ReceiveByCorrelationId(correlationId));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by the
+        /// MessageQueue matching the selection criteria, and waits until either
+        /// a message is available in the queue, or the time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan)
+        {
+            return Convert(messageQueue.ReceiveByCorrelationId(correlationId,
+                timeSpan));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(MessageQueueTransaction transaction)
+        {
+            return Convert(messageQueue.ReceiveByCorrelationId(correlationId,
+                transaction));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria,
+        /// and waits until either a message is available in the queue, or the
+        /// time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan,
+            MessageQueueTransaction transaction)
+        {
+            return Convert(messageQueue.ReceiveByCorrelationId(correlationId,
+                timeSpan, transaction));
+        }
+
+        /// <summary>
+        /// Checks if an MSMQ message matches the selection criteria.
+        /// </summary>
+        /// <param name="message">MSMQ message.</param>
+        /// <return>true if the message matches the selection criteria.</return>
+        public override bool Matches(Message message)
+        {
+            // NB: case-sensitive match
+            return message.CorrelationId == correlationId;
+        }
+	}
+}
diff --git a/src/main/csharp/Readers/ByIdMessageReader.cs b/src/main/csharp/Readers/ByIdMessageReader.cs
index f981ca8..6a544f4 100644
--- a/src/main/csharp/Readers/ByIdMessageReader.cs
+++ b/src/main/csharp/Readers/ByIdMessageReader.cs
@@ -1,136 +1,136 @@
-using System;

-using System.Messaging;

-using Apache.NMS.MSMQ;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ.Readers

-{

-    /// <summary>

-    /// MSMQ message reader, returning messages matching the specified

-    /// message identifier.

-    /// </summary>

-	public class ByIdMessageReader : AbstractMessageReader

-	{

-        private string messageId;

-

-        /// <summary>

-        /// Constructor.

-        /// </summary>

-        /// <param name="messageQueue">The MSMQ message queue from which

-        /// messages will be read.</param>

-        /// <param name="messageConverter">A message converter for mapping

-        /// MSMQ messages to NMS messages.</param>

-        /// <param name="messageId">The message identifier of messages to

-        /// be read.</param>

-        public ByIdMessageReader(MessageQueue messageQueue,

-            IMessageConverter messageConverter, string messageId)

-            : base(messageQueue, messageConverter)

-        {

-            this.messageId = messageId;

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available.

-        /// </summary>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek()

-        {

-            return Convert(messageQueue.PeekById(messageId));

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available or the specified time-out occurs.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek(TimeSpan timeSpan)

-        {

-            return Convert(messageQueue.PeekById(messageId, timeSpan));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by

-        /// the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive()

-        {

-            return Convert(messageQueue.ReceiveById(messageId));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by the

-        /// MessageQueue matching the selection criteria, and waits until either

-        /// a message is available in the queue, or the time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan)

-        {

-            return Convert(messageQueue.ReceiveById(messageId, timeSpan));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(MessageQueueTransaction transaction)

-        {

-            return Convert(messageQueue.ReceiveById(messageId, transaction));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria,

-        /// and waits until either a message is available in the queue, or the

-        /// time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan,

-            MessageQueueTransaction transaction)

-        {

-            return Convert(messageQueue.ReceiveById(messageId, timeSpan,

-                transaction));

-        }

-

-        /// <summary>

-        /// Checks if an MSMQ message matches the selection criteria.

-        /// </summary>

-        /// <param name="message">MSMQ message.</param>

-        /// <return>true if the message matches the selection criteria.</return>

-        public override bool Matches(Message message)

-        {

-            // NB: case-sensitive match

-            return message.Id == messageId;

-        }

-	}

-}

+using System;
+using System.Messaging;
+using Apache.NMS.MSMQ;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ.Readers
+{
+    /// <summary>
+    /// MSMQ message reader, returning messages matching the specified
+    /// message identifier.
+    /// </summary>
+	public class ByIdMessageReader : AbstractMessageReader
+	{
+        private string messageId;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="messageQueue">The MSMQ message queue from which
+        /// messages will be read.</param>
+        /// <param name="messageConverter">A message converter for mapping
+        /// MSMQ messages to NMS messages.</param>
+        /// <param name="messageId">The message identifier of messages to
+        /// be read.</param>
+        public ByIdMessageReader(MessageQueue messageQueue,
+            IMessageConverter messageConverter, string messageId)
+            : base(messageQueue, messageConverter)
+        {
+            this.messageId = messageId;
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available.
+        /// </summary>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek()
+        {
+            return Convert(messageQueue.PeekById(messageId));
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available or the specified time-out occurs.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek(TimeSpan timeSpan)
+        {
+            return Convert(messageQueue.PeekById(messageId, timeSpan));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by
+        /// the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive()
+        {
+            return Convert(messageQueue.ReceiveById(messageId));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by the
+        /// MessageQueue matching the selection criteria, and waits until either
+        /// a message is available in the queue, or the time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan)
+        {
+            return Convert(messageQueue.ReceiveById(messageId, timeSpan));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(MessageQueueTransaction transaction)
+        {
+            return Convert(messageQueue.ReceiveById(messageId, transaction));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria,
+        /// and waits until either a message is available in the queue, or the
+        /// time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan,
+            MessageQueueTransaction transaction)
+        {
+            return Convert(messageQueue.ReceiveById(messageId, timeSpan,
+                transaction));
+        }
+
+        /// <summary>
+        /// Checks if an MSMQ message matches the selection criteria.
+        /// </summary>
+        /// <param name="message">MSMQ message.</param>
+        /// <return>true if the message matches the selection criteria.</return>
+        public override bool Matches(Message message)
+        {
+            // NB: case-sensitive match
+            return message.Id == messageId;
+        }
+	}
+}
diff --git a/src/main/csharp/Readers/ByLookupIdMessageReader.cs b/src/main/csharp/Readers/ByLookupIdMessageReader.cs
index 421c52b..423c3a7 100644
--- a/src/main/csharp/Readers/ByLookupIdMessageReader.cs
+++ b/src/main/csharp/Readers/ByLookupIdMessageReader.cs
@@ -1,145 +1,215 @@
-using System;

-using System.Messaging;

-using Apache.NMS.MSMQ;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ.Readers

-{

-    /// <summary>

-    /// MSMQ message reader, returning messages matching the specified

-    /// lookup identifier.

-    /// </summary>

-	public class ByLookupIdMessageReader : AbstractMessageReader

-	{

-        private Int64 lookupId;

-

-        /// <summary>

-        /// Constructor.

-        /// </summary>

-        /// <param name="messageQueue">The MSMQ message queue from which

-        /// messages will be read.</param>

-        /// <param name="messageConverter">A message converter for mapping

-        /// MSMQ messages to NMS messages.</param>

-        /// <param name="lookupId">The lookup identifier of the message

-        /// to be read.</param>

-        public ByLookupIdMessageReader(MessageQueue messageQueue,

-            IMessageConverter messageConverter, Int64 lookupId)

-            : base(messageQueue, messageConverter)

-        {

-            this.lookupId = lookupId;

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available.

-        /// </summary>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek()

-        {

-            return Convert(messageQueue.PeekByLookupId(lookupId));

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available or the specified time-out occurs.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek(TimeSpan timeSpan)

-        {

-            // No time-out option for receiving messages by lookup identifiers:

-            // either the message is present in the queue, or the method throws

-            // an exception immediately if the message is not in the queue. 

-            return Convert(messageQueue.PeekByLookupId(lookupId));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by

-        /// the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive()

-        {

-            return Convert(messageQueue.ReceiveByLookupId(lookupId));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by the

-        /// MessageQueue matching the selection criteria, and waits until either

-        /// a message is available in the queue, or the time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan)

-        {

-            // No time-out option for receiving messages by lookup identifiers:

-            // either the message is present in the queue, or the method throws

-            // an exception immediately if the message is not in the queue. 

-            return Convert(messageQueue.ReceiveByLookupId(lookupId));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(MessageQueueTransaction transaction)

-        {

-            return Convert(messageQueue.ReceiveByLookupId(

-                MessageLookupAction.Current, lookupId, transaction));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria,

-        /// and waits until either a message is available in the queue, or the

-        /// time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan,

-            MessageQueueTransaction transaction)

-        {

-            // No time-out option for receiving messages by lookup identifiers:

-            // either the message is present in the queue, or the method throws

-            // an exception immediately if the message is not in the queue. 

-            return Convert(messageQueue.ReceiveByLookupId(

-                MessageLookupAction.Current, lookupId, transaction));

-        }

-

-        /// <summary>

-        /// Checks if an MSMQ message matches the selection criteria.

-        /// </summary>

-        /// <param name="message">MSMQ message.</param>

-        /// <return>true if the message matches the selection criteria.</return>

-        public override bool Matches(Message message)

-        {

-            return message.LookupId == lookupId;

-        }

-	}

-}

+using System;
+using System.Messaging;
+using Apache.NMS.MSMQ;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ.Readers
+{
+    /// <summary>
+    /// MSMQ message reader, returning messages matching the specified
+    /// lookup identifier.
+    /// </summary>
+	public class ByLookupIdMessageReader : AbstractMessageReader
+	{
+        private Int64 lookupId;
+
+        // The MSMQ documentation for MessageQueue.PeekByLookupId(*) and
+        // MessageQueue.ReceiveByLookupId(*) specifies:
+        // InvalidOperationException: The message with the specified lookupId could not be found.
+ 
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="messageQueue">The MSMQ message queue from which
+        /// messages will be read.</param>
+        /// <param name="messageConverter">A message converter for mapping
+        /// MSMQ messages to NMS messages.</param>
+        /// <param name="lookupId">The lookup identifier of the message
+        /// to be read.</param>
+        public ByLookupIdMessageReader(MessageQueue messageQueue,
+            IMessageConverter messageConverter, Int64 lookupId)
+            : base(messageQueue, messageConverter)
+        {
+            this.lookupId = lookupId;
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available.
+        /// </summary>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek()
+        {
+            try
+            {
+                return Convert(messageQueue.PeekByLookupId(lookupId));
+            }
+            catch(InvalidOperationException)
+            {
+                return null;
+            }
+            catch(Exception ex)
+            {
+                throw ex;
+            }
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available or the specified time-out occurs.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek(TimeSpan timeSpan)
+        {
+            try
+            {
+                // No time-out option for receiving messages by lookup identifiers:
+                // either the message is present in the queue, or the method throws
+                // an exception immediately if the message is not in the queue. 
+                return Convert(messageQueue.PeekByLookupId(lookupId));
+            }
+            catch(InvalidOperationException)
+            {
+                return null;
+            }
+            catch(Exception ex)
+            {
+                throw ex;
+            }
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by
+        /// the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive()
+        {
+            try
+            {
+                return Convert(messageQueue.ReceiveByLookupId(lookupId));
+            }
+            catch(InvalidOperationException)
+            {
+                return null;
+            }
+            catch(Exception ex)
+            {
+                throw ex;
+            }
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by the
+        /// MessageQueue matching the selection criteria, and waits until either
+        /// a message is available in the queue, or the time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan)
+        {
+            try
+            {
+                // No time-out option for receiving messages by lookup identifiers:
+                // either the message is present in the queue, or the method throws
+                // an exception immediately if the message is not in the queue. 
+                return Convert(messageQueue.ReceiveByLookupId(lookupId));
+            }
+            catch(InvalidOperationException)
+            {
+                return null;
+            }
+            catch(Exception ex)
+            {
+                throw ex;
+            }
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(MessageQueueTransaction transaction)
+        {
+            try
+            {
+                return Convert(messageQueue.ReceiveByLookupId(
+                    MessageLookupAction.Current, lookupId, transaction));
+            }
+            catch(InvalidOperationException)
+            {
+                return null;
+            }
+            catch(Exception ex)
+            {
+                throw ex;
+            }
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria,
+        /// and waits until either a message is available in the queue, or the
+        /// time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan,
+            MessageQueueTransaction transaction)
+        {
+            try
+            {
+                // No time-out option for receiving messages by lookup identifiers:
+                // either the message is present in the queue, or the method throws
+                // an exception immediately if the message is not in the queue. 
+                return Convert(messageQueue.ReceiveByLookupId(
+                    MessageLookupAction.Current, lookupId, transaction));
+            }
+            catch(InvalidOperationException)
+            {
+                return null;
+            }
+            catch(Exception ex)
+            {
+                throw ex;
+            }
+        }
+
+        /// <summary>
+        /// Checks if an MSMQ message matches the selection criteria.
+        /// </summary>
+        /// <param name="message">MSMQ message.</param>
+        /// <return>true if the message matches the selection criteria.</return>
+        public override bool Matches(Message message)
+        {
+            return message.LookupId == lookupId;
+        }
+	}
+}
diff --git a/src/main/csharp/Readers/BySelectorMessageReader.cs b/src/main/csharp/Readers/BySelectorMessageReader.cs
index e7cd5c3..5617784 100644
--- a/src/main/csharp/Readers/BySelectorMessageReader.cs
+++ b/src/main/csharp/Readers/BySelectorMessageReader.cs
@@ -1,290 +1,286 @@
-using System;

-using System.Messaging;

-using Apache.NMS.MSMQ;

-using Apache.NMS;

-using Apache.NMS.Selector;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ.Readers

-{

-    /// <summary>

-    /// MSMQ message reader, returning messages matching the specified

-    /// selector.

-    /// </summary>

-	public class BySelectorMessageReader : AbstractMessageReader

-	{

-        private string selector;

-        private MessageEvaluationContext evaluationContext;

-        private IBooleanExpression selectionExpression;

-

-        /// <summary>

-        /// Constructor.

-        /// </summary>

-        /// <param name="messageQueue">The MSMQ message queue from which

-        /// messages will be read.</param>

-        /// <param name="messageConverter">A message converter for mapping

-        /// MSMQ messages to NMS messages.</param>

-        /// <param name="selector">The selector string.</param>

-        public BySelectorMessageReader(MessageQueue messageQueue,

-            IMessageConverter messageConverter, string selector)

-            : base(messageQueue, messageConverter)

-        {

-            this.selector = selector;

-

-            SelectorParser selectorParser = new SelectorParser();

-            selectionExpression = selectorParser.Parse(selector);

-

-            evaluationContext = new MessageEvaluationContext(null);

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available.

-        /// </summary>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek()

-        {

-            return InternalPeek(DateTime.MaxValue, true);

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available or the specified time-out occurs.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek(TimeSpan timeSpan)

-        {

-            DateTime maxTime = DateTime.Now + timeSpan;

-            return InternalPeek(maxTime, true);

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by

-        /// the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive()

-        {

-            return InternalReceive(DateTime.MaxValue, null);

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by the

-        /// MessageQueue matching the selection criteria, and waits until either

-        /// a message is available in the queue, or the time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan)

-        {

-            return InternalReceive(DateTime.Now + timeSpan, null);

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(MessageQueueTransaction transaction)

-        {

-            return InternalReceive(DateTime.MaxValue, transaction);

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria,

-        /// and waits until either a message is available in the queue, or the

-        /// time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan,

-            MessageQueueTransaction transaction)

-        {

-            return InternalReceive(DateTime.Now + timeSpan, transaction);

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria,

-        /// and waits until either a message is available in the queue, or the

-        /// time-out expires.

-        /// </summary>

-        /// <param name="maxTime">Reception time-out.</param>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public IMessage InternalReceive(DateTime maxTime,

-            MessageQueueTransaction transaction)

-        {

-            // In a shared connection / multi-consumer context, the message may

-            // have been consumed by another client, after it was peeked but

-            // before it was peeked by this client. Hence the loop.

-            // (not sure it can be shared AND transactional, though).

-            while(true)

-            {

-                IMessage peekedMessage = InternalPeek(maxTime, false);

-

-                if(peekedMessage == null)

-                {

-                    return null;

-                }

-

-                try

-                {

-                    long lookupId = peekedMessage.Properties.GetLong("LookupId");

-

-                    Message message = (transaction == null ?

-                        messageQueue.ReceiveByLookupId(lookupId) :

-                        messageQueue.ReceiveByLookupId(

-                            MessageLookupAction.Current, lookupId, transaction));

-

-                    return Convert(message);

-                }

-                catch(InvalidOperationException exc)

-                {

-                    // TODO: filter exceptions, catch only exceptions due to                    

-                    // unknown lookup id.

-                }

-            }

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue, matching the selection criteria.

-        /// </summary>

-        /// <param name="maxTime">Reception time-out.</param>

-        /// <param name="convertBody">true if message body should be converted.</param>

-        /// <returns>Peeked message.</returns>

-        private IMessage InternalPeek(DateTime maxTime, bool convertBody)

-        {

-            TimeSpan timeSpan = maxTime - DateTime.Now;

-            if(timeSpan <= TimeSpan.Zero)

-            {

-                timeSpan = TimeSpan.Zero;

-            }

-

-            Cursor cursor = messageQueue.CreateCursor();

-

-            PeekAction action = PeekAction.Current;

-

-            while(true)

-            {

-                Message msmqMessage = null;

-

-                try

-                {

-                    msmqMessage = messageQueue.Peek(timeSpan, cursor, action);

-                }

-                catch(MessageQueueException exc)

-                {

-                    if(exc.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)

-                    {

-                        throw exc;

-                    }

-                }

-

-                if(msmqMessage == null)

-                {

-                    return null;

-                }

-

-                IMessage nmsMessage = InternalMatch(msmqMessage, convertBody);

-

-                if(nmsMessage != null)

-                {

-                    return nmsMessage;

-                }

-

-                action = PeekAction.Next;

-            }

-        }

-

-        /// <summary>

-        /// Checks if an MSMQ message matches the selection criteria. If matched

-        /// the method returns the converted NMS message. Else it returns null.

-        /// </summary>

-        /// <param name="message">The MSMQ message to check.</param>

-        /// <param name="convertBody">true if the message body should be

-        /// converted.</param>

-        /// <returns>The matching message converted to NMS, or null.</returns>

-        private IMessage InternalMatch(Message message, bool convertBody)

-        {

-            if(messageConverterEx == null)

-            {

-                IMessage nmsMessage = messageConverter.ToNmsMessage(message);

-

-                evaluationContext.Message = nmsMessage;

-

-                if(selectionExpression.Matches(evaluationContext))

-                {

-                    return nmsMessage;

-                }

-            }

-            else

-            {

-                // This version converts the message body only for those

-                // messages matching the selection criteria.

-                // Relies on MessageConverterEx for partial conversions.

-                IMessage nmsMessage = messageConverterEx.ToNmsMessage(

-                    message, false);

-

-                evaluationContext.Message = nmsMessage;

-

-                if(selectionExpression.Matches(evaluationContext))

-                {

-                    if(convertBody)

-                    {

-                        messageConverterEx.ConvertMessageBodyToNMS(

-                            message, nmsMessage);

-                    }

-

-                    return nmsMessage;

-                }

-            }

-

-            return null;

-        }

-

-        /// <summary>

-        /// Checks if an MSMQ message matches the selection criteria.

-        /// </summary>

-        /// <param name="message">MSMQ message.</param>

-        /// <return>true if the message matches the selection criteria.</return>

-        public override bool Matches(Message message)

-        {

-            IMessage nmsMessage = messageConverterEx == null ?

-                messageConverter.ToNmsMessage(message) :

-                messageConverterEx.ToNmsMessage(message, false);

-

-            evaluationContext.Message = nmsMessage;

-

-            return selectionExpression.Matches(evaluationContext);

-        }

-	}

-}

+using System;
+using System.Messaging;
+using Apache.NMS.MSMQ;
+using Apache.NMS;
+using Apache.NMS.Selector;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ.Readers
+{
+    /// <summary>
+    /// MSMQ message reader, returning messages matching the specified
+    /// selector.
+    /// </summary>
+	public class BySelectorMessageReader : AbstractMessageReader
+	{
+        private string selector;
+        private MessageEvaluationContext evaluationContext;
+        private IBooleanExpression selectionExpression;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="messageQueue">The MSMQ message queue from which
+        /// messages will be read.</param>
+        /// <param name="messageConverter">A message converter for mapping
+        /// MSMQ messages to NMS messages.</param>
+        /// <param name="selector">The selector string.</param>
+        public BySelectorMessageReader(MessageQueue messageQueue,
+            IMessageConverter messageConverter, string selector)
+            : base(messageQueue, messageConverter)
+        {
+            this.selector = selector;
+
+            SelectorParser selectorParser = new SelectorParser();
+            selectionExpression = selectorParser.Parse(selector);
+
+            evaluationContext = new MessageEvaluationContext(null);
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available.
+        /// </summary>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek()
+        {
+            return InternalPeek(DateTime.MaxValue, true);
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available or the specified time-out occurs.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek(TimeSpan timeSpan)
+        {
+            DateTime maxTime = DateTime.Now + timeSpan;
+            return InternalPeek(maxTime, true);
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by
+        /// the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive()
+        {
+            return InternalReceive(DateTime.MaxValue, null);
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by the
+        /// MessageQueue matching the selection criteria, and waits until either
+        /// a message is available in the queue, or the time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan)
+        {
+            return InternalReceive(DateTime.Now + timeSpan, null);
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(MessageQueueTransaction transaction)
+        {
+            return InternalReceive(DateTime.MaxValue, transaction);
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria,
+        /// and waits until either a message is available in the queue, or the
+        /// time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan,
+            MessageQueueTransaction transaction)
+        {
+            return InternalReceive(DateTime.Now + timeSpan, transaction);
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria,
+        /// and waits until either a message is available in the queue, or the
+        /// time-out expires.
+        /// </summary>
+        /// <param name="maxTime">Reception time-out.</param>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public IMessage InternalReceive(DateTime maxTime,
+            MessageQueueTransaction transaction)
+        {
+            // In a shared connection / multi-consumer context, the message may
+            // have been consumed by another client, after it was peeked but
+            // before it was peeked by this client. Hence the loop.
+            // (not sure it can be shared AND transactional, though).
+            while(true)
+            {
+                IMessage peekedMessage = InternalPeek(maxTime, false);
+
+                if(peekedMessage == null)
+                {
+                    return null;
+                }
+
+                try
+                {
+                    long lookupId = peekedMessage.Properties.GetLong("LookupId");
+
+                    Message message = (transaction == null ?
+                        messageQueue.ReceiveByLookupId(lookupId) :
+                        messageQueue.ReceiveByLookupId(
+                            MessageLookupAction.Current, lookupId, transaction));
+
+                    return Convert(message);
+                }
+                catch(InvalidOperationException)
+                {
+                    // TODO: filter exceptions, catch only exceptions due to                    
+                    // unknown lookup id.
+                }
+            }
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue, matching the selection criteria.
+        /// </summary>
+        /// <param name="maxTime">Reception time-out.</param>
+        /// <param name="convertBody">true if message body should be converted.</param>
+        /// <returns>Peeked message.</returns>
+        private IMessage InternalPeek(DateTime maxTime, bool convertBody)
+        {
+            TimeSpan timeSpan = maxTime - DateTime.Now;
+            if(timeSpan <= TimeSpan.Zero)
+            {
+                timeSpan = TimeSpan.Zero;
+            }
+
+            using(Cursor cursor = messageQueue.CreateCursor())
+            {
+                PeekAction action = PeekAction.Current;
+                while(true)
+                {
+                    Message msmqMessage = null;
+
+                    try
+                    {
+                        msmqMessage = messageQueue.Peek(timeSpan, cursor, action);
+                    }
+                    catch(MessageQueueException exc)
+                    {
+                        if(exc.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
+                        {
+                            return null;
+                        }
+                        throw exc;
+                    }
+
+                    IMessage nmsMessage = InternalMatch(msmqMessage, convertBody);
+
+                    if(nmsMessage != null)
+                    {
+                        return nmsMessage;
+                    }
+
+                    action = PeekAction.Next;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Checks if an MSMQ message matches the selection criteria. If matched
+        /// the method returns the converted NMS message. Else it returns null.
+        /// </summary>
+        /// <param name="message">The MSMQ message to check.</param>
+        /// <param name="convertBody">true if the message body should be
+        /// converted.</param>
+        /// <returns>The matching message converted to NMS, or null.</returns>
+        private IMessage InternalMatch(Message message, bool convertBody)
+        {
+            if(messageConverterEx == null)
+            {
+                IMessage nmsMessage = messageConverter.ToNmsMessage(message);
+
+                evaluationContext.Message = nmsMessage;
+
+                if(selectionExpression.Matches(evaluationContext))
+                {
+                    return nmsMessage;
+                }
+            }
+            else
+            {
+                // This version converts the message body only for those
+                // messages matching the selection criteria.
+                // Relies on MessageConverterEx for partial conversions.
+                IMessage nmsMessage = messageConverterEx.ToNmsMessage(
+                    message, false);
+
+                evaluationContext.Message = nmsMessage;
+
+                if(selectionExpression.Matches(evaluationContext))
+                {
+                    if(convertBody)
+                    {
+                        messageConverterEx.ConvertMessageBodyToNMS(
+                            message, nmsMessage);
+                    }
+
+                    return nmsMessage;
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Checks if an MSMQ message matches the selection criteria.
+        /// </summary>
+        /// <param name="message">MSMQ message.</param>
+        /// <return>true if the message matches the selection criteria.</return>
+        public override bool Matches(Message message)
+        {
+            IMessage nmsMessage = messageConverterEx == null ?
+                messageConverter.ToNmsMessage(message) :
+                messageConverterEx.ToNmsMessage(message, false);
+
+            evaluationContext.Message = nmsMessage;
+
+            return selectionExpression.Matches(evaluationContext);
+        }
+	}
+}
diff --git a/src/main/csharp/Readers/IMessageReader.cs b/src/main/csharp/Readers/IMessageReader.cs
index 8168664..c36323f 100644
--- a/src/main/csharp/Readers/IMessageReader.cs
+++ b/src/main/csharp/Readers/IMessageReader.cs
@@ -1,93 +1,93 @@
-using System;

-using System.Messaging;

-using Apache.NMS.MSMQ;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ.Readers

-{

-    /// <summary>

-    /// MSMQ message reader.

-    /// </summary>

-	public interface IMessageReader

-	{

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available.

-        /// </summary>

-        /// <returns>Peeked message.</returns>

-        IMessage Peek();

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available or the specified time-out occurs.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Peeked message.</returns>

-        IMessage Peek(TimeSpan timeSpan);

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by

-        /// the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <returns>Received message.</returns>

-        IMessage Receive();

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by the

-        /// MessageQueue matching the selection criteria, and waits until either

-        /// a message is available in the queue, or the time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Received message.</returns>

-        IMessage Receive(TimeSpan timeSpan);

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        IMessage Receive(MessageQueueTransaction transaction);

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria,

-        /// and waits until either a message is available in the queue, or the

-        /// time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        IMessage Receive(TimeSpan timeSpan, MessageQueueTransaction transaction);

-

-        /// <summary>

-        /// Checks if an MSMQ message matches the selection criteria.

-        /// </summary>

-        /// <param name="message">MSMQ message.</param>

-        /// <return>true if the message matches the selection criteria.</return>

-        bool Matches(Message message);

-	}

-}

+using System;
+using System.Messaging;
+using Apache.NMS.MSMQ;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ.Readers
+{
+    /// <summary>
+    /// MSMQ message reader.
+    /// </summary>
+	public interface IMessageReader
+	{
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available.
+        /// </summary>
+        /// <returns>Peeked message.</returns>
+        IMessage Peek();
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available or the specified time-out occurs.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Peeked message.</returns>
+        IMessage Peek(TimeSpan timeSpan);
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by
+        /// the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <returns>Received message.</returns>
+        IMessage Receive();
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by the
+        /// MessageQueue matching the selection criteria, and waits until either
+        /// a message is available in the queue, or the time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Received message.</returns>
+        IMessage Receive(TimeSpan timeSpan);
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        IMessage Receive(MessageQueueTransaction transaction);
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria,
+        /// and waits until either a message is available in the queue, or the
+        /// time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        IMessage Receive(TimeSpan timeSpan, MessageQueueTransaction transaction);
+
+        /// <summary>
+        /// Checks if an MSMQ message matches the selection criteria.
+        /// </summary>
+        /// <param name="message">MSMQ message.</param>
+        /// <return>true if the message matches the selection criteria.</return>
+        bool Matches(Message message);
+	}
+}
diff --git a/src/main/csharp/Readers/MessageReaderUtil.cs b/src/main/csharp/Readers/MessageReaderUtil.cs
index c303965..97d62c3 100644
--- a/src/main/csharp/Readers/MessageReaderUtil.cs
+++ b/src/main/csharp/Readers/MessageReaderUtil.cs
@@ -1,91 +1,91 @@
-using System;

-using System.Messaging;

-using System.Globalization;

-using System.Text.RegularExpressions;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ.Readers

-{

-    /// <summary>

-    /// Utility routines for creating MSMQ message readers.

-    /// </summary>

-	public static class MessageReaderUtil

-	{

-        private static Regex basicSelectorRegex =

-            new Regex(@"^\s*" +

-                      @"(NMSMessageId)\s*=\s*'([^']*)'|" +

-                      @"(NMSCorrelationId)\s*=\s*'([^']*)'|" +

-                      @"(LookupId)\s*=\s*([-+]{0,1}\d+)" +

-                      @"\s*$",

-                RegexOptions.IgnoreCase | RegexOptions.Compiled);

-

-        /// <summary>

-        /// Creates a message reader for the specified message selector.

-        /// </summary>

-        /// <param name="messageQueue">The MSMQ message queue from which

-        /// messages will be read.</param>

-        /// <param name="messageConverter">A message converter for mapping

-        /// MSMQ messages to NMS messages.</param>

-        /// <param name="selector">The message selector.</param>

-        /// <return>A reader for the specified selector.</return>

-        public static IMessageReader CreateMessageReader(

-            MessageQueue messageQueue, IMessageConverter messageConverter,

-            string selector)

-        {

-            IMessageReader reader;

-

-            if(string.IsNullOrEmpty(selector))

-            {

-                reader = new NonFilteringMessageReader(messageQueue,

-                    messageConverter);

-            }

-            else

-            {

-                Match match = basicSelectorRegex.Match(selector);

-                if(match.Success)

-                {

-                    if(!string.IsNullOrEmpty(match.Groups[1].Value))

-                    {

-                        reader = new ByIdMessageReader(messageQueue,

-                            messageConverter, match.Groups[2].Value);

-                    }

-                    else if(!string.IsNullOrEmpty(match.Groups[3].Value))

-                    {

-                        reader = new ByCorrelationIdMessageReader(messageQueue,

-                            messageConverter, match.Groups[4].Value);

-                    }

-                    else

-                    {

-                        Int64 lookupId = Int64.Parse(match.Groups[6].Value,

-                            CultureInfo.InvariantCulture);

-

-                        reader = new ByLookupIdMessageReader(messageQueue,

-                            messageConverter, lookupId);

-                    }

-                }

-                else

-                {

-                    reader = new BySelectorMessageReader(messageQueue,

-                        messageConverter, selector);

-                }

-            }

-

-            return reader;

-        }

-	}

-}

+using System;
+using System.Messaging;
+using System.Globalization;
+using System.Text.RegularExpressions;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ.Readers
+{
+    /// <summary>
+    /// Utility routines for creating MSMQ message readers.
+    /// </summary>
+	public static class MessageReaderUtil
+	{
+        private static Regex basicSelectorRegex =
+            new Regex(@"^\s*" +
+                      @"(NMSMessageId)\s*=\s*'([^']*)'|" +
+                      @"(NMSCorrelationId)\s*=\s*'([^']*)'|" +
+                      @"(LookupId)\s*=\s*([-+]{0,1}\d+)" +
+                      @"\s*$",
+                RegexOptions.IgnoreCase | RegexOptions.Compiled);
+
+        /// <summary>
+        /// Creates a message reader for the specified message selector.
+        /// </summary>
+        /// <param name="messageQueue">The MSMQ message queue from which
+        /// messages will be read.</param>
+        /// <param name="messageConverter">A message converter for mapping
+        /// MSMQ messages to NMS messages.</param>
+        /// <param name="selector">The message selector.</param>
+        /// <return>A reader for the specified selector.</return>
+        public static IMessageReader CreateMessageReader(
+            MessageQueue messageQueue, IMessageConverter messageConverter,
+            string selector)
+        {
+            IMessageReader reader;
+
+            if(string.IsNullOrEmpty(selector))
+            {
+                reader = new NonFilteringMessageReader(messageQueue,
+                    messageConverter);
+            }
+            else
+            {
+                Match match = basicSelectorRegex.Match(selector);
+                if(match.Success)
+                {
+                    if(!string.IsNullOrEmpty(match.Groups[1].Value))
+                    {
+                        reader = new ByIdMessageReader(messageQueue,
+                            messageConverter, match.Groups[2].Value);
+                    }
+                    else if(!string.IsNullOrEmpty(match.Groups[3].Value))
+                    {
+                        reader = new ByCorrelationIdMessageReader(messageQueue,
+                            messageConverter, match.Groups[4].Value);
+                    }
+                    else
+                    {
+                        Int64 lookupId = Int64.Parse(match.Groups[6].Value,
+                            CultureInfo.InvariantCulture);
+
+                        reader = new ByLookupIdMessageReader(messageQueue,
+                            messageConverter, lookupId);
+                    }
+                }
+                else
+                {
+                    reader = new BySelectorMessageReader(messageQueue,
+                        messageConverter, selector);
+                }
+            }
+
+            return reader;
+        }
+	}
+}
diff --git a/src/main/csharp/Readers/NonFilteringMessageReader.cs b/src/main/csharp/Readers/NonFilteringMessageReader.cs
index ea98baf..0b9ff7b 100644
--- a/src/main/csharp/Readers/NonFilteringMessageReader.cs
+++ b/src/main/csharp/Readers/NonFilteringMessageReader.cs
@@ -1,128 +1,128 @@
-using System;

-using System.Messaging;

-using Apache.NMS.MSMQ;

-/*

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.MSMQ.Readers

-{

-    /// <summary>

-    /// MSMQ message reader, returning all messages, without filtering.

-    /// </summary>

-	public class NonFilteringMessageReader : AbstractMessageReader

-	{

-        /// <summary>

-        /// Constructor.

-        /// </summary>

-        /// <param name="messageQueue">The MSMQ message queue from which

-        /// messages will be read.</param>

-        /// <param name="messageConverter">A message converter for mapping

-        /// MSMQ messages to NMS messages.</param>

-        public NonFilteringMessageReader(MessageQueue messageQueue,

-            IMessageConverter messageConverter)

-            : base(messageQueue, messageConverter)

-        {

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available.

-        /// </summary>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek()

-        {

-            return Convert(messageQueue.Peek());

-        }

-

-        /// <summary>

-        /// Returns without removing (peeks) the first message in the queue

-        /// referenced by this MessageQueue matching the selection criteria.

-        /// The Peek method is synchronous, so it blocks the current thread

-        /// until a message becomes available or the specified time-out occurs.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Peeked message.</returns>

-        public override IMessage Peek(TimeSpan timeSpan)

-        {

-            return Convert(messageQueue.Peek(timeSpan));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by

-        /// the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive()

-        {

-            return Convert(messageQueue.Receive());

-        }

-

-        /// <summary>

-        /// Receives the first message available in the queue referenced by the

-        /// MessageQueue matching the selection criteria, and waits until either

-        /// a message is available in the queue, or the time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan)

-        {

-            return Convert(messageQueue.Receive(timeSpan));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria.

-        /// This call is synchronous, and blocks the current thread of execution

-        /// until a message is available.

-        /// </summary>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(MessageQueueTransaction transaction)

-        {

-            return Convert(messageQueue.Receive(transaction));

-        }

-

-        /// <summary>

-        /// Receives the first message available in the transactional queue

-        /// referenced by the MessageQueue matching the selection criteria,

-        /// and waits until either a message is available in the queue, or the

-        /// time-out expires.

-        /// </summary>

-        /// <param name="timeSpan">Reception time-out.</param>

-        /// <param name="transaction">Transaction.</param>

-        /// <returns>Received message.</returns>

-        public override IMessage Receive(TimeSpan timeSpan,

-            MessageQueueTransaction transaction)

-        {

-            return Convert(messageQueue.Receive(timeSpan, transaction));

-        }

-

-        /// <summary>

-        /// Checks if an MSMQ message matches the selection criteria.

-        /// </summary>

-        /// <param name="message">MSMQ message.</param>

-        /// <return>true if the message matches the selection criteria.</return>

-        public override bool Matches(Message message)

-        {

-            return true;

-        }

-	}

-}

+using System;
+using System.Messaging;
+using Apache.NMS.MSMQ;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.NMS.MSMQ.Readers
+{
+    /// <summary>
+    /// MSMQ message reader, returning all messages, without filtering.
+    /// </summary>
+	public class NonFilteringMessageReader : AbstractMessageReader
+	{
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="messageQueue">The MSMQ message queue from which
+        /// messages will be read.</param>
+        /// <param name="messageConverter">A message converter for mapping
+        /// MSMQ messages to NMS messages.</param>
+        public NonFilteringMessageReader(MessageQueue messageQueue,
+            IMessageConverter messageConverter)
+            : base(messageQueue, messageConverter)
+        {
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available.
+        /// </summary>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek()
+        {
+            return Convert(messageQueue.Peek());
+        }
+
+        /// <summary>
+        /// Returns without removing (peeks) the first message in the queue
+        /// referenced by this MessageQueue matching the selection criteria.
+        /// The Peek method is synchronous, so it blocks the current thread
+        /// until a message becomes available or the specified time-out occurs.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Peeked message.</returns>
+        public override IMessage Peek(TimeSpan timeSpan)
+        {
+            return Convert(messageQueue.Peek(timeSpan));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by
+        /// the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive()
+        {
+            return Convert(messageQueue.Receive());
+        }
+
+        /// <summary>
+        /// Receives the first message available in the queue referenced by the
+        /// MessageQueue matching the selection criteria, and waits until either
+        /// a message is available in the queue, or the time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan)
+        {
+            return Convert(messageQueue.Receive(timeSpan));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria.
+        /// This call is synchronous, and blocks the current thread of execution
+        /// until a message is available.
+        /// </summary>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(MessageQueueTransaction transaction)
+        {
+            return Convert(messageQueue.Receive(transaction));
+        }
+
+        /// <summary>
+        /// Receives the first message available in the transactional queue
+        /// referenced by the MessageQueue matching the selection criteria,
+        /// and waits until either a message is available in the queue, or the
+        /// time-out expires.
+        /// </summary>
+        /// <param name="timeSpan">Reception time-out.</param>
+        /// <param name="transaction">Transaction.</param>
+        /// <returns>Received message.</returns>
+        public override IMessage Receive(TimeSpan timeSpan,
+            MessageQueueTransaction transaction)
+        {
+            return Convert(messageQueue.Receive(timeSpan, transaction));
+        }
+
+        /// <summary>
+        /// Checks if an MSMQ message matches the selection criteria.
+        /// </summary>
+        /// <param name="message">MSMQ message.</param>
+        /// <return>true if the message matches the selection criteria.</return>
+        public override bool Matches(Message message)
+        {
+            return true;
+        }
+	}
+}
diff --git a/src/main/csharp/Selector/ANDExpression.cs b/src/main/csharp/Selector/ANDExpression.cs
index 285efe3..976eacc 100644
--- a/src/main/csharp/Selector/ANDExpression.cs
+++ b/src/main/csharp/Selector/ANDExpression.cs
@@ -1,47 +1,46 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a logical AND combination of two expressions.

-    /// </summary>

-    public class ANDExpression : LogicExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "AND"; }

-        }

-

-        public ANDExpression(IBooleanExpression left, IBooleanExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object lvalue = Left.Evaluate(message);

-            if(lvalue == null) return null;

-            if(!(bool)lvalue) return false;

-

-            object rvalue = Right.Evaluate(message);

-            return rvalue == null ? null : rvalue;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a logical AND combination of two expressions.
+    /// </summary>
+    public class ANDExpression : LogicExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "AND"; }
+        }
+
+        public ANDExpression(IBooleanExpression left, IBooleanExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object lvalue = Left.Evaluate(message);
+            if(lvalue == null) return null;
+            if(!(bool)lvalue) return false;
+
+            object rvalue = Right.Evaluate(message);
+            return rvalue == null ? null : rvalue;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/AlignedNumericValues.cs b/src/main/csharp/Selector/AlignedNumericValues.cs
index 96e2eeb..b8bfa50 100644
--- a/src/main/csharp/Selector/AlignedNumericValues.cs
+++ b/src/main/csharp/Selector/AlignedNumericValues.cs
@@ -1,175 +1,174 @@
-using System;

-using System.Globalization;

-using System.Collections.Generic;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A couple of numeric values converted to the type of the largest type.

-    /// </summary>

-    public class AlignedNumericValues

-    {

-        private object left;

-        public object Left

-        {

-            get { return left; }

-        }

-

-        private object right;

-        public object Right

-        {

-            get { return right; }

-        }

-

-        private T type;

-        public T TypeEnum

-        {

-            get { return type; }

-        }

-

-        public Type Type

-        {

-            get { return GetType(type); }

-        }

-

-        public AlignedNumericValues(object lvalue, object rvalue)

-        {

-            if(lvalue == null || rvalue == null)

-            {

-                return;

-            }

-

-            T ltypeEnum = GetTypeEnum(lvalue);

-            T rtypeEnum = GetTypeEnum(rvalue);

-

-            type = targetType[(int)ltypeEnum][(int)rtypeEnum];

-

-            left  = (ltypeEnum == type ? lvalue : ConvertValue(lvalue, type));

-            right = (rtypeEnum == type ? rvalue : ConvertValue(rvalue, type));

-        }

-

-        public enum T

-        {

-            SByteType  =  0, // Signed 8-bit integer (-128 to 127)

-            ByteType   =  1, // Unsigned 8-bit integer (0 to 255)

-            CharType   =  2, // Unicode 16-bit character (U+0000 to U+ffff)

-            ShortType  =  3, // Signed 16-bit integer (-32 768 to 32 767)

-            UShortType =  4, // Unsigned 16-bit integer (0 to 65 535)

-            IntType    =  5, // Signed 32-bit integer (-2 147 483 648 to 2 147 483 647)

-            UIntType   =  6, // Unsigned 32-bit integer (0 to 4 294 967 295)

-            LongType   =  7, // Signed 64-bit integer (-9 223 372 036 854 775 808 to 9 223 372 036 854 775 807)

-            ULongType  =  8, // Unsigned 64-bit integer (0 to 18 446 744 073 709 551 615)

-            FloatType  =  9, // 7 digits (±1.5e−45 to ±3.4e38)

-            DoubleType = 10  // 15-16 digits (±5.0e−324 to ±1.7e308)

-        }

-

-        private static Dictionary<Type, T> typeEnums

-            = new Dictionary<Type, T>

-                {

-                    { typeof(sbyte ), T.SByteType  },

-                    { typeof(byte  ), T.ByteType   },

-                    { typeof(char  ), T.CharType   },

-                    { typeof(short ), T.ShortType  },

-                    { typeof(ushort), T.UShortType },

-                    { typeof(int   ), T.IntType    },

-                    { typeof(uint  ), T.UIntType   },

-                    { typeof(long  ), T.LongType   },

-                    { typeof(ulong ), T.ULongType  },

-                    { typeof(float ), T.FloatType  },

-                    { typeof(double), T.DoubleType }

-                };

-

-        private static T[][] targetType = new T[][]

-        {

-            //                        SByteType ,   ByteType  ,   CharType  ,   ShortType ,   UShortType,   IntType   ,   UIntType  ,   LongType  ,   ULongType ,   FloatType ,   DoubleType

-            /*SByteType */new T[] { T.SByteType , T.ShortType , T.IntType   , T.ShortType , T.IntType   , T.IntType   , T.LongType  , T.LongType  , T.LongType  , T.FloatType , T.DoubleType },

-            /*ByteType  */new T[] { T.ShortType , T.ByteType  , T.UShortType, T.ShortType , T.UShortType, T.IntType   , T.UIntType  , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },

-            /*CharType  */new T[] { T.IntType   , T.UShortType, T.CharType  , T.IntType   , T.UShortType, T.IntType   , T.LongType  , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },

-            /*ShortType */new T[] { T.ShortType , T.ShortType , T.IntType   , T.ShortType , T.IntType   , T.IntType   , T.LongType  , T.LongType  , T.LongType  , T.FloatType , T.DoubleType },

-            /*UShortType*/new T[] { T.IntType   , T.UShortType, T.UShortType, T.IntType   , T.UShortType, T.IntType   , T.UIntType  , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },

-            /*IntType   */new T[] { T.IntType   , T.IntType   , T.IntType   , T.IntType   , T.IntType   , T.IntType   , T.LongType  , T.LongType  , T.LongType  , T.FloatType , T.DoubleType },

-            /*UIntType  */new T[] { T.LongType  , T.UIntType  , T.LongType  , T.LongType  , T.UIntType  , T.LongType  , T.UIntType  , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },

-            /*LongType  */new T[] { T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.FloatType , T.DoubleType },

-            /*ULongType */new T[] { T.LongType  , T.ULongType , T.ULongType , T.LongType  , T.ULongType , T.LongType  , T.ULongType , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },

-            /*FloatType */new T[] { T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.DoubleType },

-            /*DoubleType*/new T[] { T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType }

-        };

-

-        private T GetTypeEnum(object value)

-        {

-            return GetTypeEnum(value.GetType());

-        }

-

-        private T GetTypeEnum(Type type)

-        {

-            try

-            {

-                return typeEnums[type];

-            }

-            catch

-            {

-                throw new NotSupportedException(

-                    string.Format("Unsupported data type {0}.", type));

-            }

-        }

-

-        private Type GetType(T typeEnum)

-        {

-            switch(typeEnum)

-            {

-                case T.SByteType : return typeof(sbyte );

-                case T.ByteType  : return typeof(byte  );

-                case T.CharType  : return typeof(char  );

-                case T.ShortType : return typeof(short );

-                case T.UShortType: return typeof(ushort);

-                case T.IntType   : return typeof(int   );

-                case T.UIntType  : return typeof(uint  );

-                case T.LongType  : return typeof(long  );

-                case T.ULongType : return typeof(ulong );

-                case T.FloatType : return typeof(float );

-                case T.DoubleType: return typeof(double);

-                default:

-                    throw new NotSupportedException(

-                        string.Format("Unsupported data type {0}.", typeEnum));

-            }

-        }

-

-        private object ConvertValue(object value, T targetTypeEnum)

-        {

-            switch(targetTypeEnum)

-            {

-                case T.SByteType : return Convert.ToSByte (value);

-                case T.ByteType  : return Convert.ToByte  (value);

-                case T.CharType  : return Convert.ToChar  (value);

-                case T.ShortType : return Convert.ToInt16 (value);

-                case T.UShortType: return Convert.ToUInt16(value);

-                case T.IntType   : return Convert.ToInt32 (value);

-                case T.UIntType  : return Convert.ToUInt32(value);

-                case T.LongType  : return Convert.ToInt64 (value);

-                case T.ULongType : return Convert.ToUInt64(value);

-                case T.FloatType : return Convert.ToSingle(value);

-                case T.DoubleType: return Convert.ToDouble(value);

-                default:

-                    throw new NotSupportedException(

-                        string.Format("Unsupported data type {0}.", targetTypeEnum));

-            }

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Globalization;
+using System.Collections.Generic;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A couple of numeric values converted to the type of the largest type.
+    /// </summary>
+    public class AlignedNumericValues
+    {
+        private object left;
+        public object Left
+        {
+            get { return left; }
+        }
+
+        private object right;
+        public object Right
+        {
+            get { return right; }
+        }
+
+        private T type;
+        public T TypeEnum
+        {
+            get { return type; }
+        }
+
+        public Type Type
+        {
+            get { return GetType(type); }
+        }
+
+        public AlignedNumericValues(object lvalue, object rvalue)
+        {
+            if(lvalue == null || rvalue == null)
+            {
+                return;
+            }
+
+            T ltypeEnum = GetTypeEnum(lvalue);
+            T rtypeEnum = GetTypeEnum(rvalue);
+
+            type = targetType[(int)ltypeEnum][(int)rtypeEnum];
+
+            left  = (ltypeEnum == type ? lvalue : ConvertValue(lvalue, type));
+            right = (rtypeEnum == type ? rvalue : ConvertValue(rvalue, type));
+        }
+
+        public enum T
+        {
+            SByteType  =  0, // Signed 8-bit integer (-128 to 127)
+            ByteType   =  1, // Unsigned 8-bit integer (0 to 255)
+            CharType   =  2, // Unicode 16-bit character (U+0000 to U+ffff)
+            ShortType  =  3, // Signed 16-bit integer (-32 768 to 32 767)
+            UShortType =  4, // Unsigned 16-bit integer (0 to 65 535)
+            IntType    =  5, // Signed 32-bit integer (-2 147 483 648 to 2 147 483 647)
+            UIntType   =  6, // Unsigned 32-bit integer (0 to 4 294 967 295)
+            LongType   =  7, // Signed 64-bit integer (-9 223 372 036 854 775 808 to 9 223 372 036 854 775 807)
+            ULongType  =  8, // Unsigned 64-bit integer (0 to 18 446 744 073 709 551 615)
+            FloatType  =  9, // 7 digits (±1.5e−45 to ±3.4e38)
+            DoubleType = 10  // 15-16 digits (±5.0e−324 to ±1.7e308)
+        }
+
+        private static Dictionary<Type, T> typeEnums
+            = new Dictionary<Type, T>
+                {
+                    { typeof(sbyte ), T.SByteType  },
+                    { typeof(byte  ), T.ByteType   },
+                    { typeof(char  ), T.CharType   },
+                    { typeof(short ), T.ShortType  },
+                    { typeof(ushort), T.UShortType },
+                    { typeof(int   ), T.IntType    },
+                    { typeof(uint  ), T.UIntType   },
+                    { typeof(long  ), T.LongType   },
+                    { typeof(ulong ), T.ULongType  },
+                    { typeof(float ), T.FloatType  },
+                    { typeof(double), T.DoubleType }
+                };
+
+        private static T[][] targetType = new T[][]
+        {
+            //                        SByteType ,   ByteType  ,   CharType  ,   ShortType ,   UShortType,   IntType   ,   UIntType  ,   LongType  ,   ULongType ,   FloatType ,   DoubleType
+            /*SByteType */new T[] { T.SByteType , T.ShortType , T.IntType   , T.ShortType , T.IntType   , T.IntType   , T.LongType  , T.LongType  , T.LongType  , T.FloatType , T.DoubleType },
+            /*ByteType  */new T[] { T.ShortType , T.ByteType  , T.UShortType, T.ShortType , T.UShortType, T.IntType   , T.UIntType  , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },
+            /*CharType  */new T[] { T.IntType   , T.UShortType, T.CharType  , T.IntType   , T.UShortType, T.IntType   , T.LongType  , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },
+            /*ShortType */new T[] { T.ShortType , T.ShortType , T.IntType   , T.ShortType , T.IntType   , T.IntType   , T.LongType  , T.LongType  , T.LongType  , T.FloatType , T.DoubleType },
+            /*UShortType*/new T[] { T.IntType   , T.UShortType, T.UShortType, T.IntType   , T.UShortType, T.IntType   , T.UIntType  , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },
+            /*IntType   */new T[] { T.IntType   , T.IntType   , T.IntType   , T.IntType   , T.IntType   , T.IntType   , T.LongType  , T.LongType  , T.LongType  , T.FloatType , T.DoubleType },
+            /*UIntType  */new T[] { T.LongType  , T.UIntType  , T.LongType  , T.LongType  , T.UIntType  , T.LongType  , T.UIntType  , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },
+            /*LongType  */new T[] { T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.LongType  , T.FloatType , T.DoubleType },
+            /*ULongType */new T[] { T.LongType  , T.ULongType , T.ULongType , T.LongType  , T.ULongType , T.LongType  , T.ULongType , T.LongType  , T.ULongType , T.FloatType , T.DoubleType },
+            /*FloatType */new T[] { T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.FloatType , T.DoubleType },
+            /*DoubleType*/new T[] { T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType, T.DoubleType }
+        };
+
+        private T GetTypeEnum(object value)
+        {
+            return GetTypeEnum(value.GetType());
+        }
+
+        private T GetTypeEnum(Type type)
+        {
+            try
+            {
+                return typeEnums[type];
+            }
+            catch
+            {
+                throw new NotSupportedException(
+                    string.Format("Unsupported data type {0}.", type));
+            }
+        }
+
+        private Type GetType(T typeEnum)
+        {
+            switch(typeEnum)
+            {
+                case T.SByteType : return typeof(sbyte );
+                case T.ByteType  : return typeof(byte  );
+                case T.CharType  : return typeof(char  );
+                case T.ShortType : return typeof(short );
+                case T.UShortType: return typeof(ushort);
+                case T.IntType   : return typeof(int   );
+                case T.UIntType  : return typeof(uint  );
+                case T.LongType  : return typeof(long  );
+                case T.ULongType : return typeof(ulong );
+                case T.FloatType : return typeof(float );
+                case T.DoubleType: return typeof(double);
+                default:
+                    throw new NotSupportedException(
+                        string.Format("Unsupported data type {0}.", typeEnum));
+            }
+        }
+
+        private object ConvertValue(object value, T targetTypeEnum)
+        {
+            switch(targetTypeEnum)
+            {
+                case T.SByteType : return Convert.ToSByte (value);
+                case T.ByteType  : return Convert.ToByte  (value);
+                case T.CharType  : return Convert.ToChar  (value);
+                case T.ShortType : return Convert.ToInt16 (value);
+                case T.UShortType: return Convert.ToUInt16(value);
+                case T.IntType   : return Convert.ToInt32 (value);
+                case T.UIntType  : return Convert.ToUInt32(value);
+                case T.LongType  : return Convert.ToInt64 (value);
+                case T.ULongType : return Convert.ToUInt64(value);
+                case T.FloatType : return Convert.ToSingle(value);
+                case T.DoubleType: return Convert.ToDouble(value);
+                default:
+                    throw new NotSupportedException(
+                        string.Format("Unsupported data type {0}.", targetTypeEnum));
+            }
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/ArithmeticExpression.cs b/src/main/csharp/Selector/ArithmeticExpression.cs
index a0524ee..0da9129 100644
--- a/src/main/csharp/Selector/ArithmeticExpression.cs
+++ b/src/main/csharp/Selector/ArithmeticExpression.cs
@@ -1,57 +1,56 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// An expression which performs an operation on two expression values.

-    /// </summary>

-    public abstract class ArithmeticExpression : BinaryExpression

-    {

-        public ArithmeticExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public static IExpression CreatePlus(IExpression left, IExpression right)

-        {

-            return new PlusExpression(left, right);

-        }

-

-        public static IExpression CreateMinus(IExpression left, IExpression right)

-        {

-            return new MinusExpression(left, right);

-        }

-

-        public static IExpression CreateMultiply(IExpression left, IExpression right)

-        {

-            return new MultiplyExpression(left, right);

-        }

-

-        public static IExpression CreateDivide(IExpression left, IExpression right)

-        {

-            return new DivideExpression(left, right);

-        }

-

-        public static IExpression CreateMod(IExpression left, IExpression right)

-        {

-            return new ModExpression(left, right);

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// An expression which performs an operation on two expression values.
+    /// </summary>
+    public abstract class ArithmeticExpression : BinaryExpression
+    {
+        public ArithmeticExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public static IExpression CreatePlus(IExpression left, IExpression right)
+        {
+            return new PlusExpression(left, right);
+        }
+
+        public static IExpression CreateMinus(IExpression left, IExpression right)
+        {
+            return new MinusExpression(left, right);
+        }
+
+        public static IExpression CreateMultiply(IExpression left, IExpression right)
+        {
+            return new MultiplyExpression(left, right);
+        }
+
+        public static IExpression CreateDivide(IExpression left, IExpression right)
+        {
+            return new DivideExpression(left, right);
+        }
+
+        public static IExpression CreateMod(IExpression left, IExpression right)
+        {
+            return new ModExpression(left, right);
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/BinaryExpression.cs b/src/main/csharp/Selector/BinaryExpression.cs
index 9206f8c..0cb506d 100644
--- a/src/main/csharp/Selector/BinaryExpression.cs
+++ b/src/main/csharp/Selector/BinaryExpression.cs
@@ -1,59 +1,58 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// An expression which performs an operation on two expression values.

-    /// </summary>

-    public abstract class BinaryExpression : IExpression

-    {

-        protected IExpression leftExpression;

-        public IExpression Left

-        {

-            get { return leftExpression; }

-            set { leftExpression = value; }

-        }

-

-        protected IExpression rightExpression;

-        public IExpression Right

-        {

-            get { return rightExpression; }

-            set { rightExpression = value; }

-        }

-

-        protected abstract string ExpressionSymbol

-        {

-            get;

-        }

-

-        public BinaryExpression(IExpression left, IExpression right)

-        {

-            leftExpression = left;

-            rightExpression = right;

-        }

-

-        public abstract object Evaluate(MessageEvaluationContext message);

-

-        public override string ToString()

-        {

-            return "(" + leftExpression.ToString() + " " + ExpressionSymbol + " " + rightExpression.ToString() + ")";

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// An expression which performs an operation on two expression values.
+    /// </summary>
+    public abstract class BinaryExpression : IExpression
+    {
+        protected IExpression leftExpression;
+        public IExpression Left
+        {
+            get { return leftExpression; }
+            set { leftExpression = value; }
+        }
+
+        protected IExpression rightExpression;
+        public IExpression Right
+        {
+            get { return rightExpression; }
+            set { rightExpression = value; }
+        }
+
+        protected abstract string ExpressionSymbol
+        {
+            get;
+        }
+
+        public BinaryExpression(IExpression left, IExpression right)
+        {
+            leftExpression = left;
+            rightExpression = right;
+        }
+
+        public abstract object Evaluate(MessageEvaluationContext message);
+
+        public override string ToString()
+        {
+            return "(" + leftExpression.ToString() + " " + ExpressionSymbol + " " + rightExpression.ToString() + ")";
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/BooleanCastExpression.cs b/src/main/csharp/Selector/BooleanCastExpression.cs
index 26a6e9e..ea5bf05 100644
--- a/src/main/csharp/Selector/BooleanCastExpression.cs
+++ b/src/main/csharp/Selector/BooleanCastExpression.cs
@@ -1,45 +1,44 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// An expression which casts an expression value to a boolean.

-    /// </summary>

-    public class BooleanCastExpression : BooleanUnaryExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return ""; }

-        }

-

-        public BooleanCastExpression(IExpression left)

-            : base(left)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object rvalue = Right.Evaluate(message);

-            if(rvalue == null   ) return null;

-            if(rvalue is bool   ) return (bool)rvalue;

-            return false;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// An expression which casts an expression value to a boolean.
+    /// </summary>
+    public class BooleanCastExpression : BooleanUnaryExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return ""; }
+        }
+
+        public BooleanCastExpression(IExpression left)
+            : base(left)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object rvalue = Right.Evaluate(message);
+            if(rvalue == null   ) return null;
+            if(rvalue is bool   ) return (bool)rvalue;
+            return false;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/BooleanConstantExpression.cs b/src/main/csharp/Selector/BooleanConstantExpression.cs
index eb6447a..1859436 100644
--- a/src/main/csharp/Selector/BooleanConstantExpression.cs
+++ b/src/main/csharp/Selector/BooleanConstantExpression.cs
@@ -1,38 +1,37 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// Represents a boolean constant expression.

-    /// </summary>

-    public class BooleanConstantExpression : ConstantExpression, IBooleanExpression

-    {

-        public BooleanConstantExpression(object value)

-            : base(value)

-        {

-        }

-

-        public bool Matches(MessageEvaluationContext message)

-        {

-            object value = Evaluate(message);

-            return value != null && (bool)value;            

-        }

-    }

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// Represents a boolean constant expression.
+    /// </summary>
+    public class BooleanConstantExpression : ConstantExpression, IBooleanExpression
+    {
+        public BooleanConstantExpression(object value)
+            : base(value)
+        {
+        }
+
+        public bool Matches(MessageEvaluationContext message)
+        {
+            object value = Evaluate(message);
+            return value != null && (bool)value;            
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/main/csharp/Selector/BooleanUnaryExpression.cs b/src/main/csharp/Selector/BooleanUnaryExpression.cs
index 3873050..00489d5 100644
--- a/src/main/csharp/Selector/BooleanUnaryExpression.cs
+++ b/src/main/csharp/Selector/BooleanUnaryExpression.cs
@@ -1,39 +1,38 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// An expression which performs an operation on one expression value

-    /// and returns a boolean value.

-    /// </summary>

-    public abstract class BooleanUnaryExpression : UnaryExpression, IBooleanExpression

-    {

-        public BooleanUnaryExpression(IExpression left)

-            : base(left)

-        {        	

-        }

-

-        public bool Matches(MessageEvaluationContext message)

-        {

-            object value = Evaluate(message);

-            return value != null && (bool)value;            

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// An expression which performs an operation on one expression value
+    /// and returns a boolean value.
+    /// </summary>
+    public abstract class BooleanUnaryExpression : UnaryExpression, IBooleanExpression
+    {
+        public BooleanUnaryExpression(IExpression left)
+            : base(left)
+        {        	
+        }
+
+        public bool Matches(MessageEvaluationContext message)
+        {
+            object value = Evaluate(message);
+            return value != null && (bool)value;            
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/ComparisonExpression.cs b/src/main/csharp/Selector/ComparisonExpression.cs
index 4024271..ca9a9fe 100644
--- a/src/main/csharp/Selector/ComparisonExpression.cs
+++ b/src/main/csharp/Selector/ComparisonExpression.cs
@@ -1,162 +1,161 @@
-using System;

-using System.Collections;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a comparison of two or more expressions or objects.

-    /// </summary>

-    public abstract class ComparisonExpression : BinaryExpression, IBooleanExpression

-    {

-        public ComparisonExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object lvalue = Left.Evaluate(message);

-            object rvalue = Right.Evaluate(message);

-

-            int? compared = null;

-

-            if(lvalue == null || rvalue == null)

-            {

-                if(lvalue == null && rvalue == null)

-                {

-                    compared = 0;

-                }

-            }

-            else

-            {

-                if(lvalue == rvalue)

-                {

-                    compared = 0;

-                }

-                else if(lvalue is string && rvalue is string)

-                {

-                    compared = ((string)lvalue).CompareTo(rvalue);

-                }

-                else

-                {

-                    AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);

-

-                    switch(values.TypeEnum)

-                    {

-                        case AlignedNumericValues.T.SByteType : compared = ((sbyte )values.Left).CompareTo((sbyte )values.Right); break;

-                        case AlignedNumericValues.T.ByteType  : compared = ((byte  )values.Left).CompareTo((byte  )values.Right); break;

-                        case AlignedNumericValues.T.CharType  : compared = ((char  )values.Left).CompareTo((char  )values.Right); break;

-                        case AlignedNumericValues.T.ShortType : compared = ((short )values.Left).CompareTo((short )values.Right); break;

-                        case AlignedNumericValues.T.UShortType: compared = ((ushort)values.Left).CompareTo((ushort)values.Right); break;

-                        case AlignedNumericValues.T.IntType   : compared = ((int   )values.Left).CompareTo((int   )values.Right); break;

-                        case AlignedNumericValues.T.UIntType  : compared = ((uint  )values.Left).CompareTo((uint  )values.Right); break;

-                        case AlignedNumericValues.T.LongType  : compared = ((long  )values.Left).CompareTo((long  )values.Right); break;

-                        case AlignedNumericValues.T.ULongType : compared = ((ulong )values.Left).CompareTo((ulong )values.Right); break;

-                        case AlignedNumericValues.T.FloatType : compared = ((float )values.Left).CompareTo((float )values.Right); break;

-                        case AlignedNumericValues.T.DoubleType: compared = ((double)values.Left).CompareTo((double)values.Right); break;

-                    }

-                }

-            }

-

-            return AsBoolean(compared);

-        }

-    

-        public abstract bool AsBoolean(int? compared);

-

-        public bool Matches(MessageEvaluationContext message)

-        {

-            object value = Evaluate(message);

-            return value != null && (bool)value;            

-        }

-

-        // Equality expressions

-        public static IBooleanExpression CreateEqual(IExpression left, IExpression right)

-        {

-    	    return new EqualExpression(left, right, true);

-        }

-

-        public static IBooleanExpression CreateNotEqual(IExpression left, IExpression right)

-        {

-            return new EqualExpression(left, right, false);

-        }

-

-        public static IBooleanExpression CreateIsNull(IExpression left)

-        {

-            return new IsNullExpression(left, true);

-        }

-

-        public static IBooleanExpression CreateIsNotNull(IExpression left)

-        {

-            return new IsNullExpression(left, false);

-        }

-

-        // Binary comparison expressions

-        public static IBooleanExpression CreateGreaterThan(IExpression left, IExpression right)

-        {

-    	    return new GreaterExpression(left, right);

-        }

-

-        public static IBooleanExpression CreateGreaterThanOrEqual(IExpression left, IExpression right)

-        {

-    	    return new GreaterOrEqualExpression(left, right);

-        }

-

-        public static IBooleanExpression CreateLesserThan(IExpression left, IExpression right)

-        {

-    	    return new LesserExpression(left, right);

-        }

-

-	    public static IBooleanExpression CreateLesserThanOrEqual(IExpression left, IExpression right)

-        {

-    	    return new LesserOrEqualExpression(left, right);

-        }

-

-        // Other comparison expressions

-        public static IBooleanExpression CreateLike(IExpression left, string right, string escape)

-        {

-            return new LikeExpression(left, right, escape, true);

-        }

-

-        public static IBooleanExpression CreateNotLike(IExpression left, string right, string escape)

-        {

-            return new LikeExpression(left, right, escape, false);

-        }

-

-        public static IBooleanExpression CreateBetween(IExpression value, IExpression left, IExpression right)

-        {

-            return LogicExpression.CreateAND(CreateGreaterThanOrEqual(value, left), CreateLesserThanOrEqual(value, right));

-        }

-

-        public static IBooleanExpression CreateNotBetween(IExpression value, IExpression left, IExpression right)

-        {

-            return LogicExpression.CreateOR(CreateLesserThan(value, left), CreateGreaterThan(value, right));

-        }

-

-        public static IBooleanExpression CreateIn(IExpression left, ArrayList elements)

-        {

-            return new InExpression(left, elements, true);

-        }

-

-        public static IBooleanExpression CreateNotIn(IExpression left, ArrayList elements)

-        {

-            return new InExpression(left, elements, false);

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a comparison of two or more expressions or objects.
+    /// </summary>
+    public abstract class ComparisonExpression : BinaryExpression, IBooleanExpression
+    {
+        public ComparisonExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object lvalue = Left.Evaluate(message);
+            object rvalue = Right.Evaluate(message);
+
+            int? compared = null;
+
+            if(lvalue == null || rvalue == null)
+            {
+                if(lvalue == null && rvalue == null)
+                {
+                    compared = 0;
+                }
+            }
+            else
+            {
+                if(lvalue == rvalue)
+                {
+                    compared = 0;
+                }
+                else if(lvalue is string && rvalue is string)
+                {
+                    compared = ((string)lvalue).CompareTo(rvalue);
+                }
+                else
+                {
+                    AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);
+
+                    switch(values.TypeEnum)
+                    {
+                        case AlignedNumericValues.T.SByteType : compared = ((sbyte )values.Left).CompareTo((sbyte )values.Right); break;
+                        case AlignedNumericValues.T.ByteType  : compared = ((byte  )values.Left).CompareTo((byte  )values.Right); break;
+                        case AlignedNumericValues.T.CharType  : compared = ((char  )values.Left).CompareTo((char  )values.Right); break;
+                        case AlignedNumericValues.T.ShortType : compared = ((short )values.Left).CompareTo((short )values.Right); break;
+                        case AlignedNumericValues.T.UShortType: compared = ((ushort)values.Left).CompareTo((ushort)values.Right); break;
+                        case AlignedNumericValues.T.IntType   : compared = ((int   )values.Left).CompareTo((int   )values.Right); break;
+                        case AlignedNumericValues.T.UIntType  : compared = ((uint  )values.Left).CompareTo((uint  )values.Right); break;
+                        case AlignedNumericValues.T.LongType  : compared = ((long  )values.Left).CompareTo((long  )values.Right); break;
+                        case AlignedNumericValues.T.ULongType : compared = ((ulong )values.Left).CompareTo((ulong )values.Right); break;
+                        case AlignedNumericValues.T.FloatType : compared = ((float )values.Left).CompareTo((float )values.Right); break;
+                        case AlignedNumericValues.T.DoubleType: compared = ((double)values.Left).CompareTo((double)values.Right); break;
+                    }
+                }
+            }
+
+            return AsBoolean(compared);
+        }
+    
+        public abstract bool AsBoolean(int? compared);
+
+        public bool Matches(MessageEvaluationContext message)
+        {
+            object value = Evaluate(message);
+            return value != null && (bool)value;            
+        }
+
+        // Equality expressions
+        public static IBooleanExpression CreateEqual(IExpression left, IExpression right)
+        {
+    	    return new EqualExpression(left, right, true);
+        }
+
+        public static IBooleanExpression CreateNotEqual(IExpression left, IExpression right)
+        {
+            return new EqualExpression(left, right, false);
+        }
+
+        public static IBooleanExpression CreateIsNull(IExpression left)
+        {
+            return new IsNullExpression(left, true);
+        }
+
+        public static IBooleanExpression CreateIsNotNull(IExpression left)
+        {
+            return new IsNullExpression(left, false);
+        }
+
+        // Binary comparison expressions
+        public static IBooleanExpression CreateGreaterThan(IExpression left, IExpression right)
+        {
+    	    return new GreaterExpression(left, right);
+        }
+
+        public static IBooleanExpression CreateGreaterThanOrEqual(IExpression left, IExpression right)
+        {
+    	    return new GreaterOrEqualExpression(left, right);
+        }
+
+        public static IBooleanExpression CreateLesserThan(IExpression left, IExpression right)
+        {
+    	    return new LesserExpression(left, right);
+        }
+
+	    public static IBooleanExpression CreateLesserThanOrEqual(IExpression left, IExpression right)
+        {
+    	    return new LesserOrEqualExpression(left, right);
+        }
+
+        // Other comparison expressions
+        public static IBooleanExpression CreateLike(IExpression left, string right, string escape)
+        {
+            return new LikeExpression(left, right, escape, true);
+        }
+
+        public static IBooleanExpression CreateNotLike(IExpression left, string right, string escape)
+        {
+            return new LikeExpression(left, right, escape, false);
+        }
+
+        public static IBooleanExpression CreateBetween(IExpression value, IExpression left, IExpression right)
+        {
+            return LogicExpression.CreateAND(CreateGreaterThanOrEqual(value, left), CreateLesserThanOrEqual(value, right));
+        }
+
+        public static IBooleanExpression CreateNotBetween(IExpression value, IExpression left, IExpression right)
+        {
+            return LogicExpression.CreateOR(CreateLesserThan(value, left), CreateGreaterThan(value, right));
+        }
+
+        public static IBooleanExpression CreateIn(IExpression left, ArrayList elements)
+        {
+            return new InExpression(left, elements, true);
+        }
+
+        public static IBooleanExpression CreateNotIn(IExpression left, ArrayList elements)
+        {
+            return new InExpression(left, elements, false);
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/ConstantExpression.cs b/src/main/csharp/Selector/ConstantExpression.cs
index 90dfd69..b71683d 100644
--- a/src/main/csharp/Selector/ConstantExpression.cs
+++ b/src/main/csharp/Selector/ConstantExpression.cs
@@ -1,157 +1,156 @@
-using System;

-using System.Text;

-using System.Globalization;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// Represents a constant expression.

-    /// </summary>

-    public class ConstantExpression : IExpression

-    {

-        private object value;

-        public object Value

-        {

-            get { return value; }

-        }    

-

-        public ConstantExpression(object value)

-        {

-            this.value = value;

-        }

-

-        public static ConstantExpression CreateFromDecimal(string text)

-        {

-    	    // Long integer specified ?

-    	    object value;

-            if(text.EndsWith("l") || text.EndsWith("L"))

-            {

-    		    text = text.Substring(0, text.Length - 1);

-                value = Int64.Parse(text, CultureInfo.InvariantCulture);

-            }

-            else

-            {

-                long lvalue = Int64.Parse(text, CultureInfo.InvariantCulture);

-                if(lvalue >= Int32.MinValue && lvalue <= Int32.MaxValue)

-                {

-                    value = (int)lvalue;

-                }

-                else

-                {

-                    value = lvalue;

-                }

-            }

-            return new ConstantExpression(value);

-        }

-

-        public static ConstantExpression CreateFromHex(string text)

-        {

-            long lvalue = Convert.ToInt64(text.Substring(2), 16);

-

-    	    object value;

-            if(lvalue >= Int32.MinValue && lvalue <= Int32.MaxValue)

-            {

-                value = (int)lvalue;

-            }

-            else

-            {

-                value = lvalue;

-            }

-            return new ConstantExpression(value);

-        }

-

-

-        public static ConstantExpression CreateFromOctal(string text)

-        {

-            long lvalue = Convert.ToInt64(text, 8);

-

-    	    object value;

-            if(lvalue >= Int32.MinValue && lvalue <= Int32.MaxValue)

-            {

-                value = (int)lvalue;

-            }

-            else

-            {

-                value = lvalue;

-            }

-            return new ConstantExpression(value);

-        }

-

-        public static ConstantExpression CreateFloat(string text)

-        {

-            double value = Double.Parse(text, CultureInfo.InvariantCulture);

-            return new ConstantExpression(value);

-        }

-

-        public object Evaluate(MessageEvaluationContext message)

-        {

-            return value;

-        }

-

-        public override string ToString()

-        {

-            if(value == null)

-            {

-                return "NULL";

-            }

-            if(value is bool)

-            {

-                return (bool)value ? "TRUE" : "FALSE";

-            }

-            if(value is string)

-            {

-                return EncodeString((string)value);

-            }

-            return value.ToString();

-        }

-

-        public override int GetHashCode()

-        {

-            return (value == null ? 0 : value.GetHashCode());

-        }

-

-        /// <summary>

-        /// Encodes the value of string so that it looks like it would look like

-        /// when it was provided in a selector.

-        /// </summary>

-        /// <param name="s">String to be encoded.</param>

-        /// <return>Encoded string.</return>

-        public static string EncodeString(string s)

-        {

-            StringBuilder b = new StringBuilder();

-            b.Append('\'');

-            for(int c = 0; c < s.Length; c++)

-            {

-                char ch = s[c];

-                if(ch == '\'')

-                {

-                    b.Append(ch);

-                }

-                b.Append(ch);

-            }

-            b.Append('\'');

-            return b.ToString();

-        }

-

-        public static readonly BooleanConstantExpression NULL  = new BooleanConstantExpression(null);

-        public static readonly BooleanConstantExpression TRUE  = new BooleanConstantExpression(true);

-        public static readonly BooleanConstantExpression FALSE = new BooleanConstantExpression(false);

-    }

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Text;
+using System.Globalization;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// Represents a constant expression.
+    /// </summary>
+    public class ConstantExpression : IExpression
+    {
+        private object value;
+        public object Value
+        {
+            get { return value; }
+        }    
+
+        public ConstantExpression(object value)
+        {
+            this.value = value;
+        }
+
+        public static ConstantExpression CreateFromDecimal(string text)
+        {
+    	    // Long integer specified ?
+    	    object value;
+            if(text.EndsWith("l") || text.EndsWith("L"))
+            {
+    		    text = text.Substring(0, text.Length - 1);
+                value = Int64.Parse(text, CultureInfo.InvariantCulture);
+            }
+            else
+            {
+                long lvalue = Int64.Parse(text, CultureInfo.InvariantCulture);
+                if(lvalue >= Int32.MinValue && lvalue <= Int32.MaxValue)
+                {
+                    value = (int)lvalue;
+                }
+                else
+                {
+                    value = lvalue;
+                }
+            }
+            return new ConstantExpression(value);
+        }
+
+        public static ConstantExpression CreateFromHex(string text)
+        {
+            long lvalue = Convert.ToInt64(text.Substring(2), 16);
+
+    	    object value;
+            if(lvalue >= Int32.MinValue && lvalue <= Int32.MaxValue)
+            {
+                value = (int)lvalue;
+            }
+            else
+            {
+                value = lvalue;
+            }
+            return new ConstantExpression(value);
+        }
+
+
+        public static ConstantExpression CreateFromOctal(string text)
+        {
+            long lvalue = Convert.ToInt64(text, 8);
+
+    	    object value;
+            if(lvalue >= Int32.MinValue && lvalue <= Int32.MaxValue)
+            {
+                value = (int)lvalue;
+            }
+            else
+            {
+                value = lvalue;
+            }
+            return new ConstantExpression(value);
+        }
+
+        public static ConstantExpression CreateFloat(string text)
+        {
+            double value = Double.Parse(text, CultureInfo.InvariantCulture);
+            return new ConstantExpression(value);
+        }
+
+        public object Evaluate(MessageEvaluationContext message)
+        {
+            return value;
+        }
+
+        public override string ToString()
+        {
+            if(value == null)
+            {
+                return "NULL";
+            }
+            if(value is bool)
+            {
+                return (bool)value ? "TRUE" : "FALSE";
+            }
+            if(value is string)
+            {
+                return EncodeString((string)value);
+            }
+            return value.ToString();
+        }
+
+        public override int GetHashCode()
+        {
+            return (value == null ? 0 : value.GetHashCode());
+        }
+
+        /// <summary>
+        /// Encodes the value of string so that it looks like it would look like
+        /// when it was provided in a selector.
+        /// </summary>
+        /// <param name="s">String to be encoded.</param>
+        /// <return>Encoded string.</return>
+        public static string EncodeString(string s)
+        {
+            StringBuilder b = new StringBuilder();
+            b.Append('\'');
+            for(int c = 0; c < s.Length; c++)
+            {
+                char ch = s[c];
+                if(ch == '\'')
+                {
+                    b.Append(ch);
+                }
+                b.Append(ch);
+            }
+            b.Append('\'');
+            return b.ToString();
+        }
+
+        public static readonly BooleanConstantExpression NULL  = new BooleanConstantExpression(null);
+        public static readonly BooleanConstantExpression TRUE  = new BooleanConstantExpression(true);
+        public static readonly BooleanConstantExpression FALSE = new BooleanConstantExpression(false);
+    }
 }
\ No newline at end of file
diff --git a/src/main/csharp/Selector/DivideExpression.cs b/src/main/csharp/Selector/DivideExpression.cs
index e280ec8..63f13aa 100644
--- a/src/main/csharp/Selector/DivideExpression.cs
+++ b/src/main/csharp/Selector/DivideExpression.cs
@@ -1,67 +1,66 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a division of two expressions.

-    /// </summary>

-    public class DivideExpression : ArithmeticExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "/"; }

-        }

-

-        public DivideExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object lvalue = Left.Evaluate(message);

-            if(lvalue == null) return null;

-

-            object rvalue = Right.Evaluate(message);

-            if(rvalue == null) return null;

-

-            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);

-

-            object result = null;

-

-            switch(values.TypeEnum)

-            {

-                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left / (sbyte )values.Right; break;

-                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left / (byte  )values.Right; break;

-                case AlignedNumericValues.T.CharType  : result = (char  )values.Left / (char  )values.Right; break;

-                case AlignedNumericValues.T.ShortType : result = (short )values.Left / (short )values.Right; break;

-                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left / (ushort)values.Right; break;

-                case AlignedNumericValues.T.IntType   : result = (int   )values.Left / (int   )values.Right; break;

-                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left / (uint  )values.Right; break;

-                case AlignedNumericValues.T.LongType  : result = (long  )values.Left / (long  )values.Right; break;

-                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left / (ulong )values.Right; break;

-                case AlignedNumericValues.T.FloatType : result = (float )values.Left / (float )values.Right; break;

-                case AlignedNumericValues.T.DoubleType: result = (double)values.Left / (double)values.Right; break;

-            }

-

-            return result;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a division of two expressions.
+    /// </summary>
+    public class DivideExpression : ArithmeticExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "/"; }
+        }
+
+        public DivideExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object lvalue = Left.Evaluate(message);
+            if(lvalue == null) return null;
+
+            object rvalue = Right.Evaluate(message);
+            if(rvalue == null) return null;
+
+            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);
+
+            object result = null;
+
+            switch(values.TypeEnum)
+            {
+                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left / (sbyte )values.Right; break;
+                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left / (byte  )values.Right; break;
+                case AlignedNumericValues.T.CharType  : result = (char  )values.Left / (char  )values.Right; break;
+                case AlignedNumericValues.T.ShortType : result = (short )values.Left / (short )values.Right; break;
+                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left / (ushort)values.Right; break;
+                case AlignedNumericValues.T.IntType   : result = (int   )values.Left / (int   )values.Right; break;
+                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left / (uint  )values.Right; break;
+                case AlignedNumericValues.T.LongType  : result = (long  )values.Left / (long  )values.Right; break;
+                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left / (ulong )values.Right; break;
+                case AlignedNumericValues.T.FloatType : result = (float )values.Left / (float )values.Right; break;
+                case AlignedNumericValues.T.DoubleType: result = (double)values.Left / (double)values.Right; break;
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/EqualExpression.cs b/src/main/csharp/Selector/EqualExpression.cs
index 0e9a792..af48080 100644
--- a/src/main/csharp/Selector/EqualExpression.cs
+++ b/src/main/csharp/Selector/EqualExpression.cs
@@ -1,47 +1,46 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing an equality or inequality comparison

-    /// of two expressions.

-    /// </summary>

-    public class EqualExpression : ComparisonExpression

-    {

-        private bool notNot;

-

-        protected override string ExpressionSymbol

-        {

-            get { return notNot ? "=" : "<>"; }

-        }

-

-        public EqualExpression(IExpression left, IExpression right, bool notNot)

-            : base(left, right)

-        {

-            this.notNot = notNot;

-        }

-

-        public override bool AsBoolean(int? compared)

-        {

-            bool answer = (compared.HasValue ? compared.Value == 0 : false);

-            return notNot ? answer : !answer;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing an equality or inequality comparison
+    /// of two expressions.
+    /// </summary>
+    public class EqualExpression : ComparisonExpression
+    {
+        private bool notNot;
+
+        protected override string ExpressionSymbol
+        {
+            get { return notNot ? "=" : "<>"; }
+        }
+
+        public EqualExpression(IExpression left, IExpression right, bool notNot)
+            : base(left, right)
+        {
+            this.notNot = notNot;
+        }
+
+        public override bool AsBoolean(int? compared)
+        {
+            bool answer = (compared.HasValue ? compared.Value == 0 : false);
+            return notNot ? answer : !answer;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/GreaterExpression.cs b/src/main/csharp/Selector/GreaterExpression.cs
index eb264e5..012f3fb 100644
--- a/src/main/csharp/Selector/GreaterExpression.cs
+++ b/src/main/csharp/Selector/GreaterExpression.cs
@@ -1,42 +1,41 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a greater than comparison of two expressions.

-    /// </summary>

-    public class GreaterExpression : ComparisonExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return ">"; }

-        }

-

-        public GreaterExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override bool AsBoolean(int? compared)

-        {

-            return compared.HasValue ? compared.Value > 0 : false;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a greater than comparison of two expressions.
+    /// </summary>
+    public class GreaterExpression : ComparisonExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return ">"; }
+        }
+
+        public GreaterExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override bool AsBoolean(int? compared)
+        {
+            return compared.HasValue ? compared.Value > 0 : false;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/GreaterOrEqualExpression.cs b/src/main/csharp/Selector/GreaterOrEqualExpression.cs
index 7a456f8..df8cc6f 100644
--- a/src/main/csharp/Selector/GreaterOrEqualExpression.cs
+++ b/src/main/csharp/Selector/GreaterOrEqualExpression.cs
@@ -1,43 +1,42 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a greater than or equal comparison

-    /// of two expressions.

-    /// </summary>

-    public class GreaterOrEqualExpression : ComparisonExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return ">="; }

-        }

-

-        public GreaterOrEqualExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override bool AsBoolean(int? compared)

-        {

-            return compared.HasValue ? compared.Value >= 0 : false;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a greater than or equal comparison
+    /// of two expressions.
+    /// </summary>
+    public class GreaterOrEqualExpression : ComparisonExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return ">="; }
+        }
+
+        public GreaterOrEqualExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override bool AsBoolean(int? compared)
+        {
+            return compared.HasValue ? compared.Value >= 0 : false;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/IBooleanExpression.cs b/src/main/csharp/Selector/IBooleanExpression.cs
index af6c0f5..bf5a833 100644
--- a/src/main/csharp/Selector/IBooleanExpression.cs
+++ b/src/main/csharp/Selector/IBooleanExpression.cs
@@ -1,35 +1,34 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// An IBooleanExpression is an expression that always

-    /// produces a boolean result.

-    /// </summary>

-    public interface IBooleanExpression : IExpression

-    {

-        /// <summary>

-        /// Checks if expression evaluates to <c>true</c>.

-        /// </summary>

-        /// <param name="message">Evaluation context.</param>

-        /// <return><c>true</c> if the expression evaluates to <c>true</c>.</return>

-        bool Matches(MessageEvaluationContext message);

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// An IBooleanExpression is an expression that always
+    /// produces a boolean result.
+    /// </summary>
+    public interface IBooleanExpression : IExpression
+    {
+        /// <summary>
+        /// Checks if expression evaluates to <c>true</c>.
+        /// </summary>
+        /// <param name="message">Evaluation context.</param>
+        /// <return><c>true</c> if the expression evaluates to <c>true</c>.</return>
+        bool Matches(MessageEvaluationContext message);
+    }
+}
diff --git a/src/main/csharp/Selector/IExpression.cs b/src/main/csharp/Selector/IExpression.cs
index 30fb893..833c6b5 100644
--- a/src/main/csharp/Selector/IExpression.cs
+++ b/src/main/csharp/Selector/IExpression.cs
@@ -1,35 +1,34 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// Represents an expression

-    /// </summary>

-    public interface IExpression

-    {

-        /// <summary>

-        /// Evaluates the expression.

-        /// </summary>

-        /// <param name="message">Evaluation context.</param>

-        /// <return>The result of the evaluation.</return>

-        object Evaluate(MessageEvaluationContext message);

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// Represents an expression
+    /// </summary>
+    public interface IExpression
+    {
+        /// <summary>
+        /// Evaluates the expression.
+        /// </summary>
+        /// <param name="message">Evaluation context.</param>
+        /// <return>The result of the evaluation.</return>
+        object Evaluate(MessageEvaluationContext message);
+    }
+}
     
\ No newline at end of file
diff --git a/src/main/csharp/Selector/InExpression.cs b/src/main/csharp/Selector/InExpression.cs
index cd2d7ea..cbf3e60 100644
--- a/src/main/csharp/Selector/InExpression.cs
+++ b/src/main/csharp/Selector/InExpression.cs
@@ -1,98 +1,97 @@
-using System;

-using System.Text;

-using System.Collections;

-using System.Collections.Generic;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A boolean expression which checks if an expression value is

-    /// contained in a list of defined values.

-    /// </summary>

-    public class InExpression : BooleanUnaryExpression

-    {

-        private bool notNot;

-        private ArrayList elements;

-        private HashSet<string> hashset;

-

-        protected override string ExpressionSymbol

-        {

-            get { return notNot ? "IN" : "NOT IN"; }

-        }

-

-        public InExpression(IExpression right, ArrayList elements, bool notNot)

-            : base(right)

-        {

-            this.notNot = notNot;

-

-            this.elements = elements;

-            this.hashset = new HashSet<string>();

-

-            foreach(object element in elements)

-            {

-                hashset.Add((string)element);

-            }

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object rvalue = Right.Evaluate(message);

-

-            bool answer = false;

-            if(rvalue != null && (rvalue is string))

-            {

-                answer = hashset.Contains((string)rvalue);

-            }

-

-            return notNot ? answer : !answer;

-        }

-

-        public override string ToString()

-        {

-            StringBuilder answer = new StringBuilder();

-            answer.Append(Right);

-            answer.Append(" ");

-            answer.Append(ExpressionSymbol);

-            answer.Append(" (");

-

-            for(int i = 0; i < elements.Count; i++)

-            {

-                if(i > 0) answer.Append(", ");

-

-                string s = (string)elements[i];

-

-                answer.Append('\'');

-                for(int c = 0; c < s.Length; c++)

-                {

-                    char ch = s[c];

-                    if(ch == '\'')

-                    {

-                        answer.Append(ch);

-                    }

-                    answer.Append(ch);

-                }

-                answer.Append('\'');

-            }

-

-            answer.Append(")");

-            return answer.ToString();

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A boolean expression which checks if an expression value is
+    /// contained in a list of defined values.
+    /// </summary>
+    public class InExpression : BooleanUnaryExpression
+    {
+        private bool notNot;
+        private ArrayList elements;
+        private HashSet<string> hashset;
+
+        protected override string ExpressionSymbol
+        {
+            get { return notNot ? "IN" : "NOT IN"; }
+        }
+
+        public InExpression(IExpression right, ArrayList elements, bool notNot)
+            : base(right)
+        {
+            this.notNot = notNot;
+
+            this.elements = elements;
+            this.hashset = new HashSet<string>();
+
+            foreach(object element in elements)
+            {
+                hashset.Add((string)element);
+            }
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object rvalue = Right.Evaluate(message);
+
+            bool answer = false;
+            if(rvalue != null && (rvalue is string))
+            {
+                answer = hashset.Contains((string)rvalue);
+            }
+
+            return notNot ? answer : !answer;
+        }
+
+        public override string ToString()
+        {
+            StringBuilder answer = new StringBuilder();
+            answer.Append(Right);
+            answer.Append(" ");
+            answer.Append(ExpressionSymbol);
+            answer.Append(" (");
+
+            for(int i = 0; i < elements.Count; i++)
+            {
+                if(i > 0) answer.Append(", ");
+
+                string s = (string)elements[i];
+
+                answer.Append('\'');
+                for(int c = 0; c < s.Length; c++)
+                {
+                    char ch = s[c];
+                    if(ch == '\'')
+                    {
+                        answer.Append(ch);
+                    }
+                    answer.Append(ch);
+                }
+                answer.Append('\'');
+            }
+
+            answer.Append(")");
+            return answer.ToString();
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/IsNullExpression.cs b/src/main/csharp/Selector/IsNullExpression.cs
index 28d89a2..6ad0436 100644
--- a/src/main/csharp/Selector/IsNullExpression.cs
+++ b/src/main/csharp/Selector/IsNullExpression.cs
@@ -1,59 +1,58 @@
-using System;

-using System.Text;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A boolean expression which checks if an expression value is null.

-    /// </summary>

-    public class IsNullExpression : BooleanUnaryExpression

-    {

-        private bool notNot;

-

-        protected override string ExpressionSymbol

-        {

-            get { return notNot ? "IS NULL" : "IS NOT NULL"; }

-        }

-

-        public IsNullExpression(IExpression right, bool notNot)

-            : base(right)

-        {

-            this.notNot = notNot;

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object rvalue = Right.Evaluate(message);

-

-            bool answer = (rvalue == null || rvalue == ConstantExpression.NULL);

-

-            return notNot ? answer : !answer;

-        }

-

-        public override string ToString()

-        {

-            StringBuilder answer = new StringBuilder();

-            answer.Append(Right);

-            answer.Append(" ");

-            answer.Append(ExpressionSymbol);

-            return answer.ToString();

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Text;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A boolean expression which checks if an expression value is null.
+    /// </summary>
+    public class IsNullExpression : BooleanUnaryExpression
+    {
+        private bool notNot;
+
+        protected override string ExpressionSymbol
+        {
+            get { return notNot ? "IS NULL" : "IS NOT NULL"; }
+        }
+
+        public IsNullExpression(IExpression right, bool notNot)
+            : base(right)
+        {
+            this.notNot = notNot;
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object rvalue = Right.Evaluate(message);
+
+            bool answer = (rvalue == null || rvalue == ConstantExpression.NULL);
+
+            return notNot ? answer : !answer;
+        }
+
+        public override string ToString()
+        {
+            StringBuilder answer = new StringBuilder();
+            answer.Append(Right);
+            answer.Append(" ");
+            answer.Append(ExpressionSymbol);
+            return answer.ToString();
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/LesserExpression.cs b/src/main/csharp/Selector/LesserExpression.cs
index 4be2c9d..24b707b 100644
--- a/src/main/csharp/Selector/LesserExpression.cs
+++ b/src/main/csharp/Selector/LesserExpression.cs
@@ -1,42 +1,41 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a lesser than comparison of two expressions.

-    /// </summary>

-    public class LesserExpression : ComparisonExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "<"; }

-        }

-

-        public LesserExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override bool AsBoolean(int? compared)

-        {

-            return compared.HasValue ? compared.Value < 0 : false;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a lesser than comparison of two expressions.
+    /// </summary>
+    public class LesserExpression : ComparisonExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "<"; }
+        }
+
+        public LesserExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override bool AsBoolean(int? compared)
+        {
+            return compared.HasValue ? compared.Value < 0 : false;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/LesserOrEqualExpression.cs b/src/main/csharp/Selector/LesserOrEqualExpression.cs
index abdc7e5..f4a99db 100644
--- a/src/main/csharp/Selector/LesserOrEqualExpression.cs
+++ b/src/main/csharp/Selector/LesserOrEqualExpression.cs
@@ -1,43 +1,42 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a lesser than or equal comparison

-    /// of two expressions.

-    /// </summary>

-    public class LesserOrEqualExpression : ComparisonExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "<="; }

-        }

-

-        public LesserOrEqualExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override bool AsBoolean(int? compared)

-        {

-            return compared.HasValue ? compared.Value <= 0 : false;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a lesser than or equal comparison
+    /// of two expressions.
+    /// </summary>
+    public class LesserOrEqualExpression : ComparisonExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "<="; }
+        }
+
+        public LesserOrEqualExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override bool AsBoolean(int? compared)
+        {
+            return compared.HasValue ? compared.Value <= 0 : false;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/LikeExpression.cs b/src/main/csharp/Selector/LikeExpression.cs
index 8317bd6..41be1bd 100644
--- a/src/main/csharp/Selector/LikeExpression.cs
+++ b/src/main/csharp/Selector/LikeExpression.cs
@@ -1,124 +1,123 @@
-using System;

-using System.Text;

-using System.Text.RegularExpressions;

-using System.Globalization;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a string matching comparison.

-    /// </summary>

-    public class LikeExpression : BooleanUnaryExpression

-    {

-        private bool notNot;

-        private Regex pattern;

-

-        protected override string ExpressionSymbol

-        {

-            get { return notNot ? "LIKE" : "NOT LIKE"; }

-        }

-

-        public LikeExpression(IExpression left, string like, string escape, bool notNot)

-            : base(left)

-        {

-            this.notNot = notNot;

-

-            bool doEscape = false;

-            char escapeChar = '%';

-

-            if(escape != null)

-            {

-                if(escape.Length != 1)

-                {

-                    throw new ApplicationException("The ESCAPE string litteral is invalid.  It can only be one character.  Litteral used: " + escape);

-                }

-                doEscape = true;

-                escapeChar = escape[0];

-            }

-

-            StringBuilder temp = new StringBuilder();

-            StringBuilder regexp = new StringBuilder(like.Length * 2);

-            regexp.Append("^"); // The beginning of the input

-            for(int c = 0; c < like.Length; c++)

-            {

-                char ch = like[c];

-                if(doEscape && (ch == escapeChar))

-                {

-                    c++;

-                    if(c >= like.Length)

-                    {

-                        // nothing left to escape...

-                        break;

-                    }

-                    temp.Append(like[c]);

-                }

-                else if(ch == '%')

-                {

-                    if(temp.Length > 0)

-                    {

-                        regexp.Append(Regex.Escape(temp.ToString()));

-                        temp.Length = 0;

-                    }

-                    regexp.Append(".*?"); // Do a non-greedy match 

-                }

-                else if(c == '_')

-                {

-                    if(temp.Length > 0)

-                    {

-                        regexp.Append(Regex.Escape(temp.ToString()));

-                        temp.Length = 0;

-                    }

-                    regexp.Append("."); // match one 

-                }

-                else

-                {

-                    temp.Append(ch);

-                }

-            }

-            if(temp.Length > 0)

-            {

-                regexp.Append(Regex.Escape(temp.ToString()));

-            }

-            regexp.Append("$"); // The end of the input

-

-            pattern = new Regex(regexp.ToString(), RegexOptions.Singleline | RegexOptions.Compiled);

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object rvalue = this.Right.Evaluate(message);

-

-            bool answer = false;

-            if(rvalue != null)

-            {

-                if(rvalue is string)

-                {

-                    answer = pattern.IsMatch((string)rvalue);

-                }

-                else

-                {

-                    //throw new ApplicationException("LIKE can only operate on string identifiers. LIKE attemped on " + rvalue.GetType().ToString());

-                }

-            }

-

-            return notNot ? answer : !answer;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Globalization;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a string matching comparison.
+    /// </summary>
+    public class LikeExpression : BooleanUnaryExpression
+    {
+        private bool notNot;
+        private Regex pattern;
+
+        protected override string ExpressionSymbol
+        {
+            get { return notNot ? "LIKE" : "NOT LIKE"; }
+        }
+
+        public LikeExpression(IExpression left, string like, string escape, bool notNot)
+            : base(left)
+        {
+            this.notNot = notNot;
+
+            bool doEscape = false;
+            char escapeChar = '%';
+
+            if(escape != null)
+            {
+                if(escape.Length != 1)
+                {
+                    throw new ApplicationException("The ESCAPE string litteral is invalid.  It can only be one character.  Litteral used: " + escape);
+                }
+                doEscape = true;
+                escapeChar = escape[0];
+            }
+
+            StringBuilder temp = new StringBuilder();
+            StringBuilder regexp = new StringBuilder(like.Length * 2);
+            regexp.Append("^"); // The beginning of the input
+            for(int c = 0; c < like.Length; c++)
+            {
+                char ch = like[c];
+                if(doEscape && (ch == escapeChar))
+                {
+                    c++;
+                    if(c >= like.Length)
+                    {
+                        // nothing left to escape...
+                        break;
+                    }
+                    temp.Append(like[c]);
+                }
+                else if(ch == '%')
+                {
+                    if(temp.Length > 0)
+                    {
+                        regexp.Append(Regex.Escape(temp.ToString()));
+                        temp.Length = 0;
+                    }
+                    regexp.Append(".*?"); // Do a non-greedy match 
+                }
+                else if(c == '_')
+                {
+                    if(temp.Length > 0)
+                    {
+                        regexp.Append(Regex.Escape(temp.ToString()));
+                        temp.Length = 0;
+                    }
+                    regexp.Append("."); // match one 
+                }
+                else
+                {
+                    temp.Append(ch);
+                }
+            }
+            if(temp.Length > 0)
+            {
+                regexp.Append(Regex.Escape(temp.ToString()));
+            }
+            regexp.Append("$"); // The end of the input
+
+            pattern = new Regex(regexp.ToString(), RegexOptions.Singleline | RegexOptions.Compiled);
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object rvalue = this.Right.Evaluate(message);
+
+            bool answer = false;
+            if(rvalue != null)
+            {
+                if(rvalue is string)
+                {
+                    answer = pattern.IsMatch((string)rvalue);
+                }
+                else
+                {
+                    //throw new ApplicationException("LIKE can only operate on string identifiers. LIKE attemped on " + rvalue.GetType().ToString());
+                }
+            }
+
+            return notNot ? answer : !answer;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/LogicExpression.cs b/src/main/csharp/Selector/LogicExpression.cs
index 61617a4..8e60fb0 100644
--- a/src/main/csharp/Selector/LogicExpression.cs
+++ b/src/main/csharp/Selector/LogicExpression.cs
@@ -1,48 +1,47 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a logical combination of two objects.

-    /// </summary>

-    public abstract class LogicExpression : BinaryExpression, IBooleanExpression

-    {

-        public LogicExpression(IBooleanExpression left, IBooleanExpression right)

-            : base(left, right)

-        {

-        }

-

-        public bool Matches(MessageEvaluationContext message)

-        {

-            object value = Evaluate(message);

-            return value != null && (bool)value;            

-        }

-

-        public static IBooleanExpression CreateOR(IBooleanExpression left, IBooleanExpression right)

-        {

-            return new ORExpression(left, right);

-        }

-

-        public static IBooleanExpression CreateAND(IBooleanExpression left, IBooleanExpression right)

-        {

-            return new ANDExpression(left, right);

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a logical combination of two objects.
+    /// </summary>
+    public abstract class LogicExpression : BinaryExpression, IBooleanExpression
+    {
+        public LogicExpression(IBooleanExpression left, IBooleanExpression right)
+            : base(left, right)
+        {
+        }
+
+        public bool Matches(MessageEvaluationContext message)
+        {
+            object value = Evaluate(message);
+            return value != null && (bool)value;            
+        }
+
+        public static IBooleanExpression CreateOR(IBooleanExpression left, IBooleanExpression right)
+        {
+            return new ORExpression(left, right);
+        }
+
+        public static IBooleanExpression CreateAND(IBooleanExpression left, IBooleanExpression right)
+        {
+            return new ANDExpression(left, right);
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/MessageEvaluationContext.cs b/src/main/csharp/Selector/MessageEvaluationContext.cs
index 054d911..6f26d0f 100644
--- a/src/main/csharp/Selector/MessageEvaluationContext.cs
+++ b/src/main/csharp/Selector/MessageEvaluationContext.cs
@@ -1,78 +1,77 @@
-using System;

-using Apache.NMS;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// MessageEvaluationContext is used to cache selection results.

-    /// 

-    /// A message usually has multiple selectors applied against it. Some selector

-    /// have a high cost of evaluating against the message. Those selectors may whish

-    /// to cache evaluation results associated with the message in the

-    /// MessageEvaluationContext.

-    /// </summary>

-    public class MessageEvaluationContext

-    {

-        private IMessage nmsMessage;

-        public IMessage Message

-        {

-            get { return nmsMessage; }

-            set { nmsMessage = value; }

-        }

-

-        public MessageEvaluationContext(IMessage message)

-        {

-            nmsMessage = message;

-        }

-

-        public object GetProperty(string name)

-        {

-            if(name.Length > 3 && 

-               string.Compare(name.Substring(0, 3), "JMS", true) == 0)

-            {

-                if(string.Compare(name, "JMSCorrelationID", true) == 0)

-                {

-                    return nmsMessage.NMSCorrelationID;

-                }

-                if(string.Compare(name, "JMSMessageID", true) == 0)

-                {

-                    return nmsMessage.NMSMessageId;

-                }

-                if(string.Compare(name, "JMSPriority", true) == 0)

-                {

-                    return nmsMessage.NMSPriority;

-                }

-                if(string.Compare(name, "JMSTimestamp", true) == 0)

-                {

-                    return nmsMessage.NMSTimestamp;

-                }

-                if(string.Compare(name, "JMSType", true) == 0)

-                {

-                    return nmsMessage.NMSType;

-                }

-                if(string.Compare(name, "JMSDeliveryMode", true) == 0)

-                {

-                    return nmsMessage.NMSDeliveryMode;

-                }

-            }

-            return nmsMessage.Properties[name];

-        }

-    }

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// MessageEvaluationContext is used to cache selection results.
+    /// 
+    /// A message usually has multiple selectors applied against it. Some selector
+    /// have a high cost of evaluating against the message. Those selectors may whish
+    /// to cache evaluation results associated with the message in the
+    /// MessageEvaluationContext.
+    /// </summary>
+    public class MessageEvaluationContext
+    {
+        private IMessage nmsMessage;
+        public IMessage Message
+        {
+            get { return nmsMessage; }
+            set { nmsMessage = value; }
+        }
+
+        public MessageEvaluationContext(IMessage message)
+        {
+            nmsMessage = message;
+        }
+
+        public object GetProperty(string name)
+        {
+            if(name.Length > 3 && 
+               string.Compare(name.Substring(0, 3), "JMS", true) == 0)
+            {
+                if(string.Compare(name, "JMSCorrelationID", true) == 0)
+                {
+                    return nmsMessage.NMSCorrelationID;
+                }
+                if(string.Compare(name, "JMSMessageID", true) == 0)
+                {
+                    return nmsMessage.NMSMessageId;
+                }
+                if(string.Compare(name, "JMSPriority", true) == 0)
+                {
+                    return nmsMessage.NMSPriority;
+                }
+                if(string.Compare(name, "JMSTimestamp", true) == 0)
+                {
+                    return nmsMessage.NMSTimestamp;
+                }
+                if(string.Compare(name, "JMSType", true) == 0)
+                {
+                    return nmsMessage.NMSType;
+                }
+                if(string.Compare(name, "JMSDeliveryMode", true) == 0)
+                {
+                    return nmsMessage.NMSDeliveryMode;
+                }
+            }
+            return nmsMessage.Properties[name];
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/main/csharp/Selector/MinusExpression.cs b/src/main/csharp/Selector/MinusExpression.cs
index 260e5e8..b2bc845 100644
--- a/src/main/csharp/Selector/MinusExpression.cs
+++ b/src/main/csharp/Selector/MinusExpression.cs
@@ -1,67 +1,66 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a substraction of two expressions.

-    /// </summary>

-    public class MinusExpression : ArithmeticExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "-"; }

-        }

-

-        public MinusExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object lvalue = Left.Evaluate(message);

-            if(lvalue == null) return null;

-

-            object rvalue = Right.Evaluate(message);

-            if(rvalue == null) return null;

-

-            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);

-

-            object result = null;

-

-            switch(values.TypeEnum)

-            {

-                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left - (sbyte )values.Right; break;

-                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left - (byte  )values.Right; break;

-                case AlignedNumericValues.T.CharType  : result = (char  )values.Left - (char  )values.Right; break;

-                case AlignedNumericValues.T.ShortType : result = (short )values.Left - (short )values.Right; break;

-                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left - (ushort)values.Right; break;

-                case AlignedNumericValues.T.IntType   : result = (int   )values.Left - (int   )values.Right; break;

-                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left - (uint  )values.Right; break;

-                case AlignedNumericValues.T.LongType  : result = (long  )values.Left - (long  )values.Right; break;

-                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left - (ulong )values.Right; break;

-                case AlignedNumericValues.T.FloatType : result = (float )values.Left - (float )values.Right; break;

-                case AlignedNumericValues.T.DoubleType: result = (double)values.Left - (double)values.Right; break;

-            }

-

-            return result;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a substraction of two expressions.
+    /// </summary>
+    public class MinusExpression : ArithmeticExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "-"; }
+        }
+
+        public MinusExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object lvalue = Left.Evaluate(message);
+            if(lvalue == null) return null;
+
+            object rvalue = Right.Evaluate(message);
+            if(rvalue == null) return null;
+
+            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);
+
+            object result = null;
+
+            switch(values.TypeEnum)
+            {
+                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left - (sbyte )values.Right; break;
+                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left - (byte  )values.Right; break;
+                case AlignedNumericValues.T.CharType  : result = (char  )values.Left - (char  )values.Right; break;
+                case AlignedNumericValues.T.ShortType : result = (short )values.Left - (short )values.Right; break;
+                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left - (ushort)values.Right; break;
+                case AlignedNumericValues.T.IntType   : result = (int   )values.Left - (int   )values.Right; break;
+                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left - (uint  )values.Right; break;
+                case AlignedNumericValues.T.LongType  : result = (long  )values.Left - (long  )values.Right; break;
+                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left - (ulong )values.Right; break;
+                case AlignedNumericValues.T.FloatType : result = (float )values.Left - (float )values.Right; break;
+                case AlignedNumericValues.T.DoubleType: result = (double)values.Left - (double)values.Right; break;
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/ModExpression.cs b/src/main/csharp/Selector/ModExpression.cs
index 386c08d..0ed5234 100644
--- a/src/main/csharp/Selector/ModExpression.cs
+++ b/src/main/csharp/Selector/ModExpression.cs
@@ -1,67 +1,66 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a modulo of two expressions.

-    /// </summary>

-    public class ModExpression : ArithmeticExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "%"; }

-        }

-

-        public ModExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object lvalue = Left.Evaluate(message);

-            if(lvalue == null) return null;

-

-            object rvalue = Right.Evaluate(message);

-            if(rvalue == null) return null;

-

-            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);

-

-            object result = null;

-

-            switch(values.TypeEnum)

-            {

-                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left % (sbyte )values.Right; break;

-                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left % (byte  )values.Right; break;

-                case AlignedNumericValues.T.CharType  : result = (char  )values.Left % (char  )values.Right; break;

-                case AlignedNumericValues.T.ShortType : result = (short )values.Left % (short )values.Right; break;

-                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left % (ushort)values.Right; break;

-                case AlignedNumericValues.T.IntType   : result = (int   )values.Left % (int   )values.Right; break;

-                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left % (uint  )values.Right; break;

-                case AlignedNumericValues.T.LongType  : result = (long  )values.Left % (long  )values.Right; break;

-                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left % (ulong )values.Right; break;

-                case AlignedNumericValues.T.FloatType : result = (float )values.Left % (float )values.Right; break;

-                case AlignedNumericValues.T.DoubleType: result = (double)values.Left % (double)values.Right; break;

-            }

-

-            return result;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a modulo of two expressions.
+    /// </summary>
+    public class ModExpression : ArithmeticExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "%"; }
+        }
+
+        public ModExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object lvalue = Left.Evaluate(message);
+            if(lvalue == null) return null;
+
+            object rvalue = Right.Evaluate(message);
+            if(rvalue == null) return null;
+
+            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);
+
+            object result = null;
+
+            switch(values.TypeEnum)
+            {
+                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left % (sbyte )values.Right; break;
+                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left % (byte  )values.Right; break;
+                case AlignedNumericValues.T.CharType  : result = (char  )values.Left % (char  )values.Right; break;
+                case AlignedNumericValues.T.ShortType : result = (short )values.Left % (short )values.Right; break;
+                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left % (ushort)values.Right; break;
+                case AlignedNumericValues.T.IntType   : result = (int   )values.Left % (int   )values.Right; break;
+                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left % (uint  )values.Right; break;
+                case AlignedNumericValues.T.LongType  : result = (long  )values.Left % (long  )values.Right; break;
+                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left % (ulong )values.Right; break;
+                case AlignedNumericValues.T.FloatType : result = (float )values.Left % (float )values.Right; break;
+                case AlignedNumericValues.T.DoubleType: result = (double)values.Left % (double)values.Right; break;
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/MultiplyExpression.cs b/src/main/csharp/Selector/MultiplyExpression.cs
index 0009092..130783f 100644
--- a/src/main/csharp/Selector/MultiplyExpression.cs
+++ b/src/main/csharp/Selector/MultiplyExpression.cs
@@ -1,67 +1,66 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a multiplication of two expressions.

-    /// </summary>

-    public class MultiplyExpression : ArithmeticExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "*"; }

-        }

-

-        public MultiplyExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object lvalue = Left.Evaluate(message);

-            if(lvalue == null) return null;

-

-            object rvalue = Right.Evaluate(message);

-            if(rvalue == null) return null;

-

-            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);

-

-            object result = null;

-

-            switch(values.TypeEnum)

-            {

-                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left * (sbyte )values.Right; break;

-                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left * (byte  )values.Right; break;

-                case AlignedNumericValues.T.CharType  : result = (char  )values.Left * (char  )values.Right; break;

-                case AlignedNumericValues.T.ShortType : result = (short )values.Left * (short )values.Right; break;

-                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left * (ushort)values.Right; break;

-                case AlignedNumericValues.T.IntType   : result = (int   )values.Left * (int   )values.Right; break;

-                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left * (uint  )values.Right; break;

-                case AlignedNumericValues.T.LongType  : result = (long  )values.Left * (long  )values.Right; break;

-                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left * (ulong )values.Right; break;

-                case AlignedNumericValues.T.FloatType : result = (float )values.Left * (float )values.Right; break;

-                case AlignedNumericValues.T.DoubleType: result = (double)values.Left * (double)values.Right; break;

-            }

-

-            return result;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a multiplication of two expressions.
+    /// </summary>
+    public class MultiplyExpression : ArithmeticExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "*"; }
+        }
+
+        public MultiplyExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object lvalue = Left.Evaluate(message);
+            if(lvalue == null) return null;
+
+            object rvalue = Right.Evaluate(message);
+            if(rvalue == null) return null;
+
+            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);
+
+            object result = null;
+
+            switch(values.TypeEnum)
+            {
+                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left * (sbyte )values.Right; break;
+                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left * (byte  )values.Right; break;
+                case AlignedNumericValues.T.CharType  : result = (char  )values.Left * (char  )values.Right; break;
+                case AlignedNumericValues.T.ShortType : result = (short )values.Left * (short )values.Right; break;
+                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left * (ushort)values.Right; break;
+                case AlignedNumericValues.T.IntType   : result = (int   )values.Left * (int   )values.Right; break;
+                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left * (uint  )values.Right; break;
+                case AlignedNumericValues.T.LongType  : result = (long  )values.Left * (long  )values.Right; break;
+                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left * (ulong )values.Right; break;
+                case AlignedNumericValues.T.FloatType : result = (float )values.Left * (float )values.Right; break;
+                case AlignedNumericValues.T.DoubleType: result = (double)values.Left * (double)values.Right; break;
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/NOTExpression.cs b/src/main/csharp/Selector/NOTExpression.cs
index 6d6ef55..a8b1c33 100644
--- a/src/main/csharp/Selector/NOTExpression.cs
+++ b/src/main/csharp/Selector/NOTExpression.cs
@@ -1,45 +1,44 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// An expression which negates a boolean expression value.

-    /// </summary>

-    public class NOTExpression : BooleanUnaryExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "NOT"; }

-        }

-

-        public NOTExpression(IExpression left)

-            : base(left)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object rvalue = Right.Evaluate(message);

-            if(rvalue == null   ) return null;

-            if(rvalue is bool   ) return !(bool)rvalue;

-            return null;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// An expression which negates a boolean expression value.
+    /// </summary>
+    public class NOTExpression : BooleanUnaryExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "NOT"; }
+        }
+
+        public NOTExpression(IExpression left)
+            : base(left)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object rvalue = Right.Evaluate(message);
+            if(rvalue == null   ) return null;
+            if(rvalue is bool   ) return !(bool)rvalue;
+            return null;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/NegateExpression.cs b/src/main/csharp/Selector/NegateExpression.cs
index 0496b6f..f074590 100644
--- a/src/main/csharp/Selector/NegateExpression.cs
+++ b/src/main/csharp/Selector/NegateExpression.cs
@@ -1,51 +1,50 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// An expression which negates a numeric expression value.

-    /// </summary>

-    public class NegateExpression : UnaryExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "-"; }

-        }

-

-        public NegateExpression(IExpression left)

-            : base(left)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object rvalue = Right.Evaluate(message);

-            if(rvalue == null   ) return null;

-            if(rvalue is int    ) return -(int    )rvalue;

-            if(rvalue is long   ) return -(long   )rvalue;

-            if(rvalue is double ) return -(double )rvalue;

-            if(rvalue is float  ) return -(float  )rvalue;

-            if(rvalue is decimal) return -(decimal)rvalue;

-            if(rvalue is short  ) return -(short  )rvalue;

-            if(rvalue is byte   ) return -(byte   )rvalue;

-            return null;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// An expression which negates a numeric expression value.
+    /// </summary>
+    public class NegateExpression : UnaryExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "-"; }
+        }
+
+        public NegateExpression(IExpression left)
+            : base(left)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object rvalue = Right.Evaluate(message);
+            if(rvalue == null   ) return null;
+            if(rvalue is int    ) return -(int    )rvalue;
+            if(rvalue is long   ) return -(long   )rvalue;
+            if(rvalue is double ) return -(double )rvalue;
+            if(rvalue is float  ) return -(float  )rvalue;
+            if(rvalue is decimal) return -(decimal)rvalue;
+            if(rvalue is short  ) return -(short  )rvalue;
+            if(rvalue is byte   ) return -(byte   )rvalue;
+            return null;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/ORExpression.cs b/src/main/csharp/Selector/ORExpression.cs
index 86648bc..b2ed7f3 100644
--- a/src/main/csharp/Selector/ORExpression.cs
+++ b/src/main/csharp/Selector/ORExpression.cs
@@ -1,46 +1,45 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing a logical OR combination of two expressions.

-    /// </summary>

-    public class ORExpression : LogicExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "OR"; }

-        }

-

-        public ORExpression(IBooleanExpression left, IBooleanExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object lvalue = Left.Evaluate(message);

-            if(lvalue != null && (bool)lvalue) return true;

-

-            object rvalue = Right.Evaluate(message);

-            return rvalue == null ? null : rvalue;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing a logical OR combination of two expressions.
+    /// </summary>
+    public class ORExpression : LogicExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "OR"; }
+        }
+
+        public ORExpression(IBooleanExpression left, IBooleanExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object lvalue = Left.Evaluate(message);
+            if(lvalue != null && (bool)lvalue) return true;
+
+            object rvalue = Right.Evaluate(message);
+            return rvalue == null ? null : rvalue;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/ParseException.cs b/src/main/csharp/Selector/ParseException.cs
index f1b6d60..17706e1 100644
--- a/src/main/csharp/Selector/ParseException.cs
+++ b/src/main/csharp/Selector/ParseException.cs
@@ -1,197 +1,197 @@
-/* Generated By:CSharpCC: Do not edit this line. ParseException.cs Version 3.2 */

-/// <summary>

-/// This exception is thrown when parse errors are encountered.

-/// </summary>

-/// <remarks>

-/// You can explicitly create objects of this exception type by

-/// calling the method GenerateParseException in the generated

-/// parser.

-/// <para>

-/// You can modify this class to customize your error reporting

-/// mechanisms so long as you retain the public fields.

-/// </para>

-/// </remarks>

-public  class ParseException : System.Exception {

-

-  /**

-   * This constructor is used by the method "GenerateParseException"

-   * in the generated parser. Calling this constructor generates

-   * a new object of this type with the fields "currentToken",

-   * "expectedTokenSequences", and "tokenImage" set.  The boolean

-   * flag "specialConstructor" is also set to true to indicate that

-   * this constructor was used to create this object.

-   * This constructor calls its super class with the empty string

-   * to force the "toString" method of parent class "Throwable" to

-   * print the error message in the form:

-   *     ParseException: result of getMessage

-   */

-  public ParseException(Token currentTokenVal,

-                        int[][] expectedTokenSequencesVal,

-                        string[] tokenImageVal

-                       ) : base("") {

-    specialConstructor = true;

-    currentToken = currentTokenVal;

-    expectedTokenSequences = expectedTokenSequencesVal;

-    tokenImage = tokenImageVal;

-  }

-

-  /**

-   * The following constructors are for use by you for whatever

-   * purpose you can think of.  Constructing the exception in this

-   * manner makes the exception behave in the normal way - i.e., as

-   * documented in the class "Exception".  The fields "errorToken",

-   * "expectedTokenSequences", and "tokenImage" do not contain

-   * relevant information.  The CSharpCC generated code does not use

-   * these constructors.

-   */

-

-  public ParseException() :

-    base() {

-    specialConstructor = false;

-  }

-

-  public ParseException(string message) :

-    base(message) {

-    specialConstructor = false;

-  }

-

-  /**

-   * This variable determines which constructor was used to create

-   * this object and thereby affects the semantics of the

-   * "getMessage" method (see below).

-   */

-  protected bool specialConstructor;

-

-  /**

-   * This is the last token that has been consumed successfully.  If

-   * this object has been created due to a parse error, the token

-   * followng this token will (therefore) be the first error token.

-   */

-  public Token currentToken;

-

-  /**

-   * Each entry in this array is an array of integers.  Each array

-   * of integers represents a sequence of tokens (by their ordinal

-   * values) that is expected at this point of the parse.

-   */

-  public int[][] expectedTokenSequences;

-

-  /**

-   * This is a reference to the "tokenImage" array of the generated

-   * parser within which the parse error occurred.  This array is

-   * defined in the generated ...Constants interface.

-   */

-  public string[] tokenImage;

-

-  /**

-   * This method has the standard behavior when this object has been

-   * created using the standard constructors.  Otherwise, it uses

-   * "currentToken" and "expectedTokenSequences" to generate a parse

-   * error message and returns it.  If this object has been created

-   * due to a parse error, and you do not catch it (it gets thrown

-   * from the parser), then this method is called during the printing

-   * of the final stack trace, and hence the correct error message

-   * gets displayed.

-   */

-  public override string Message {

-    get {

-      if (!specialConstructor) {

-        return base.Message;

-      }

-      string expected = "";

-      int maxSize = 0;

-      for (int i = 0; i < expectedTokenSequences.Length; i++) {

-        if (maxSize < expectedTokenSequences[i].Length) {

-          maxSize = expectedTokenSequences[i].Length;

-        }

-        for (int j = 0; j < expectedTokenSequences[i].Length; j++) {

-          expected += tokenImage[expectedTokenSequences[i][j]] + " ";

-        }

-        if (expectedTokenSequences[i][expectedTokenSequences[i].Length - 1] != 0) {

-          expected += "...";

-        }

-        expected += eol + "    ";

-      }

-      string retval = "Encountered \"";

-      Token tok = currentToken.next;

-      for (int i = 0; i < maxSize; i++) {

-        if (i != 0) retval += " ";

-        if (tok.kind == 0) {

-          retval += tokenImage[0];

-          break;

-        }

-        retval += AddEscapes(tok.image);

-        tok = tok.next; 

-      }

-      if (currentToken.next.kind == 0) {

-        retval += "\" after line ";

-      } else {

-        retval += "\" at line ";

-      }

-      retval += currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;

-      retval += "." + eol;

-      if (expectedTokenSequences.Length == 1) {

-        retval += "Was expecting:" + eol + "    ";

-      } else {

-        retval += "Was expecting one of:" + eol + "    ";

-      }

-      retval += expected;

-      return retval;

-    }

-  }

-

-  /**

-   * The end of line string for this machine.

-   */

-  protected string eol = System.Environment.NewLine;

- 

-  /**

-   * Used to convert raw characters to their escaped version

-   * when these raw version cannot be used as part of an ASCII

-   * string literal.

-   */

-  protected string AddEscapes(string str) {

-      System.Text.StringBuilder retval = new System.Text.StringBuilder();

-      char ch;

-      for (int i = 0; i < str.Length; i++) {

-        switch (str[i]) {

-           case '\0' :

-              continue;

-           case '\b':

-              retval.Append("\\b");

-              continue;

-           case '\t':

-              retval.Append("\\t");

-              continue;

-           case '\n':

-              retval.Append("\\n");

-              continue;

-           case '\f':

-              retval.Append("\\f");

-              continue;

-           case '\r':

-              retval.Append("\\r");

-              continue;

-           case '\"':

-              retval.Append("\\\"");

-              continue;

-           case '\'':

-              retval.Append("\\\'");

-              continue;

-           case '\\':

-              retval.Append("\\\\");

-              continue;

-           default:

-              if ((ch = str[i]) < 0x20 || ch > 0x7e) {

-                 string s = "0000" + System.Convert.ToString((int)ch, 16);

-                 retval.Append("\\u" + s.Substring(s.Length - 4, s.Length - (s.Length - 4)));

-              } else {

-                 retval.Append(ch);

-              }

-              continue;

-        }

-      }

-      return retval.ToString();

-   }

-

-}

+/* Generated By:CSharpCC: Do not edit this line. ParseException.cs Version 3.2 */
+/// <summary>
+/// This exception is thrown when parse errors are encountered.
+/// </summary>
+/// <remarks>
+/// You can explicitly create objects of this exception type by
+/// calling the method GenerateParseException in the generated
+/// parser.
+/// <para>
+/// You can modify this class to customize your error reporting
+/// mechanisms so long as you retain the public fields.
+/// </para>
+/// </remarks>
+public  class ParseException : System.Exception {
+
+  /**
+   * This constructor is used by the method "GenerateParseException"
+   * in the generated parser. Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.  The boolean
+   * flag "specialConstructor" is also set to true to indicate that
+   * this constructor was used to create this object.
+   * This constructor calls its super class with the empty string
+   * to force the "toString" method of parent class "Throwable" to
+   * print the error message in the form:
+   *     ParseException: result of getMessage
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        string[] tokenImageVal
+                       ) : base("") {
+    specialConstructor = true;
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Exception".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The CSharpCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() :
+    base() {
+    specialConstructor = false;
+  }
+
+  public ParseException(string message) :
+    base(message) {
+    specialConstructor = false;
+  }
+
+  /**
+   * This variable determines which constructor was used to create
+   * this object and thereby affects the semantics of the
+   * "getMessage" method (see below).
+   */
+  protected bool specialConstructor;
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public string[] tokenImage;
+
+  /**
+   * This method has the standard behavior when this object has been
+   * created using the standard constructors.  Otherwise, it uses
+   * "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser), then this method is called during the printing
+   * of the final stack trace, and hence the correct error message
+   * gets displayed.
+   */
+  public override string Message {
+    get {
+      if (!specialConstructor) {
+        return base.Message;
+      }
+      string expected = "";
+      int maxSize = 0;
+      for (int i = 0; i < expectedTokenSequences.Length; i++) {
+        if (maxSize < expectedTokenSequences[i].Length) {
+          maxSize = expectedTokenSequences[i].Length;
+        }
+        for (int j = 0; j < expectedTokenSequences[i].Length; j++) {
+          expected += tokenImage[expectedTokenSequences[i][j]] + " ";
+        }
+        if (expectedTokenSequences[i][expectedTokenSequences[i].Length - 1] != 0) {
+          expected += "...";
+        }
+        expected += eol + "    ";
+      }
+      string retval = "Encountered \"";
+      Token tok = currentToken.next;
+      for (int i = 0; i < maxSize; i++) {
+        if (i != 0) retval += " ";
+        if (tok.kind == 0) {
+          retval += tokenImage[0];
+          break;
+        }
+        retval += AddEscapes(tok.image);
+        tok = tok.next; 
+      }
+      if (currentToken.next.kind == 0) {
+        retval += "\" after line ";
+      } else {
+        retval += "\" at line ";
+      }
+      retval += currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+      retval += "." + eol;
+      if (expectedTokenSequences.Length == 1) {
+        retval += "Was expecting:" + eol + "    ";
+      } else {
+        retval += "Was expecting one of:" + eol + "    ";
+      }
+      retval += expected;
+      return retval;
+    }
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected string eol = System.Environment.NewLine;
+ 
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  protected string AddEscapes(string str) {
+      System.Text.StringBuilder retval = new System.Text.StringBuilder();
+      char ch;
+      for (int i = 0; i < str.Length; i++) {
+        switch (str[i]) {
+           case '\0' :
+              continue;
+           case '\b':
+              retval.Append("\\b");
+              continue;
+           case '\t':
+              retval.Append("\\t");
+              continue;
+           case '\n':
+              retval.Append("\\n");
+              continue;
+           case '\f':
+              retval.Append("\\f");
+              continue;
+           case '\r':
+              retval.Append("\\r");
+              continue;
+           case '\"':
+              retval.Append("\\\"");
+              continue;
+           case '\'':
+              retval.Append("\\\'");
+              continue;
+           case '\\':
+              retval.Append("\\\\");
+              continue;
+           default:
+              if ((ch = str[i]) < 0x20 || ch > 0x7e) {
+                 string s = "0000" + System.Convert.ToString((int)ch, 16);
+                 retval.Append("\\u" + s.Substring(s.Length - 4, s.Length - (s.Length - 4)));
+              } else {
+                 retval.Append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.ToString();
+   }
+
+}
diff --git a/src/main/csharp/Selector/PlusExpression.cs b/src/main/csharp/Selector/PlusExpression.cs
index 450b653..b966765 100644
--- a/src/main/csharp/Selector/PlusExpression.cs
+++ b/src/main/csharp/Selector/PlusExpression.cs
@@ -1,68 +1,67 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// A filter performing an addition of two expressions.

-    /// </summary>

-    public class PlusExpression : ArithmeticExpression

-    {

-        protected override string ExpressionSymbol

-        {

-            get { return "+"; }

-        }

-

-        public PlusExpression(IExpression left, IExpression right)

-            : base(left, right)

-        {

-        }

-

-        public override object Evaluate(MessageEvaluationContext message)

-        {

-            object lvalue = Left.Evaluate(message);

-            if(lvalue == null) return null;

-

-            object rvalue = Right.Evaluate(message);

-            if(lvalue is string) return (string)lvalue + rvalue;

-            if(rvalue == null) return null;

-

-            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);

-

-            object result = null;

-

-            switch(values.TypeEnum)

-            {

-                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left + (sbyte )values.Right; break;

-                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left + (byte  )values.Right; break;

-                case AlignedNumericValues.T.CharType  : result = (char  )values.Left + (char  )values.Right; break;

-                case AlignedNumericValues.T.ShortType : result = (short )values.Left + (short )values.Right; break;

-                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left + (ushort)values.Right; break;

-                case AlignedNumericValues.T.IntType   : result = (int   )values.Left + (int   )values.Right; break;

-                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left + (uint  )values.Right; break;

-                case AlignedNumericValues.T.LongType  : result = (long  )values.Left + (long  )values.Right; break;

-                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left + (ulong )values.Right; break;

-                case AlignedNumericValues.T.FloatType : result = (float )values.Left + (float )values.Right; break;

-                case AlignedNumericValues.T.DoubleType: result = (double)values.Left + (double)values.Right; break;

-            }

-

-            return result;

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// A filter performing an addition of two expressions.
+    /// </summary>
+    public class PlusExpression : ArithmeticExpression
+    {
+        protected override string ExpressionSymbol
+        {
+            get { return "+"; }
+        }
+
+        public PlusExpression(IExpression left, IExpression right)
+            : base(left, right)
+        {
+        }
+
+        public override object Evaluate(MessageEvaluationContext message)
+        {
+            object lvalue = Left.Evaluate(message);
+            if(lvalue == null) return null;
+
+            object rvalue = Right.Evaluate(message);
+            if(lvalue is string) return (string)lvalue + rvalue;
+            if(rvalue == null) return null;
+
+            AlignedNumericValues values = new AlignedNumericValues(lvalue, rvalue);
+
+            object result = null;
+
+            switch(values.TypeEnum)
+            {
+                case AlignedNumericValues.T.SByteType : result = (sbyte )values.Left + (sbyte )values.Right; break;
+                case AlignedNumericValues.T.ByteType  : result = (byte  )values.Left + (byte  )values.Right; break;
+                case AlignedNumericValues.T.CharType  : result = (char  )values.Left + (char  )values.Right; break;
+                case AlignedNumericValues.T.ShortType : result = (short )values.Left + (short )values.Right; break;
+                case AlignedNumericValues.T.UShortType: result = (ushort)values.Left + (ushort)values.Right; break;
+                case AlignedNumericValues.T.IntType   : result = (int   )values.Left + (int   )values.Right; break;
+                case AlignedNumericValues.T.UIntType  : result = (uint  )values.Left + (uint  )values.Right; break;
+                case AlignedNumericValues.T.LongType  : result = (long  )values.Left + (long  )values.Right; break;
+                case AlignedNumericValues.T.ULongType : result = (ulong )values.Left + (ulong )values.Right; break;
+                case AlignedNumericValues.T.FloatType : result = (float )values.Left + (float )values.Right; break;
+                case AlignedNumericValues.T.DoubleType: result = (double)values.Left + (double)values.Right; break;
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/PropertyExpression.cs b/src/main/csharp/Selector/PropertyExpression.cs
index 8d00757..0cd5c47 100644
--- a/src/main/csharp/Selector/PropertyExpression.cs
+++ b/src/main/csharp/Selector/PropertyExpression.cs
@@ -1,53 +1,52 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// Represents a property expression.

-    /// </summary>

-    public class PropertyExpression : IExpression

-    {

-        private string name;

-        public string Name

-        {

-            get { return name; }

-        }

-

-        public PropertyExpression(string name)

-        {

-            this.name = name;

-        }

-

-        public object Evaluate(MessageEvaluationContext message)

-        {

-            return message.GetProperty(name);

-        }

-

-        public override string ToString()

-        {

-            return name;

-        }

-

-        public override int GetHashCode()

-        {

-            return name.GetHashCode();

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// Represents a property expression.
+    /// </summary>
+    public class PropertyExpression : IExpression
+    {
+        private string name;
+        public string Name
+        {
+            get { return name; }
+        }
+
+        public PropertyExpression(string name)
+        {
+            this.name = name;
+        }
+
+        public object Evaluate(MessageEvaluationContext message)
+        {
+            return message.GetProperty(name);
+        }
+
+        public override string ToString()
+        {
+            return name;
+        }
+
+        public override int GetHashCode()
+        {
+            return name.GetHashCode();
+        }
+    }
+}
diff --git a/src/main/csharp/Selector/SelectorParser.cs b/src/main/csharp/Selector/SelectorParser.cs
index 92226ac..efb05f5 100644
--- a/src/main/csharp/Selector/SelectorParser.cs
+++ b/src/main/csharp/Selector/SelectorParser.cs
@@ -1,1172 +1,1171 @@
-/* Generated By:CSharpCC: Do not edit this line. SelectorParser.cs */

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-using System;

-using System.IO;

-using System.Text;

-using System.Collections;

-

-using Apache.NMS;

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// JMS Selector Parser generated by <a href="https://github.com/deveel/csharpcc">CSharpCC</a>

-    /// 

-    /// Do not edit this .cs file directly - it is autogenerated from SelectorParser.csc

-    /// using <c>csharpcc.exe -UNICODE_INPUT=true SelectorParser.csc</c>.

-    /// 

-    /// SelectorParser.csc is adapted from

-    /// <a href="https://raw.githubusercontent.com/apache/activemq/activemq-4.0/activemq-core/src/main/grammar/SelectorParser.jj">

-    /// ActiveMQ 4.0 SelectorParser.jj</a>

-    /// </summary>

-    public class SelectorParser : SelectorParserConstants {

-

-        public SelectorParser()

-            : this(new StringReader(""))

-        {

-        }

-

-        public IBooleanExpression Parse(string selector)

-        {

-            this.ReInit(new StringReader(selector));

-

-            try

-            {

-                return this.JmsSelector();

-            }

-            catch(Exception e)

-            {

-                    throw new InvalidSelectorException(selector, e);

-            }

-        }

-

-        private IBooleanExpression AsBooleanExpression(IExpression value)

-        {

-            if(value is IBooleanExpression)

-            {

-                return (IBooleanExpression)value;

-            }

-            if(value is PropertyExpression)

-            {

-                return UnaryExpression.CreateBooleanCast(value);

-            }

-            throw new ParseException("IExpression will not result in a boolean value: " + value);

-        }

-

-// ----------------------------------------------------------------------------

-// Grammar

-// ----------------------------------------------------------------------------

-  public IBooleanExpression JmsSelector() {

-    IExpression left = null;

-    left = GetOrExpression();

-        {return AsBooleanExpression(left);}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public IExpression GetOrExpression() {

-    IExpression left;

-    IExpression right;

-    left = GetAndExpression();

-    while (true) {

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case OR:

-        ;

-        break;

-      default:

-        goto label_1;

-      }

-      mcc_consume_token(OR);

-      right = GetAndExpression();

-                left = LogicExpression.CreateOR(AsBooleanExpression(left), AsBooleanExpression(right));

-    }label_1: ;

-    

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public IExpression GetAndExpression() {

-    IExpression left;

-    IExpression right;

-    left = GetEqualityExpression();

-    while (true) {

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case AND:

-        ;

-        break;

-      default:

-        goto label_2;

-      }

-      mcc_consume_token(AND);

-      right = GetEqualityExpression();

-                left = LogicExpression.CreateAND(AsBooleanExpression(left), AsBooleanExpression(right));

-    }label_2: ;

-    

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public IExpression GetEqualityExpression() {

-    IExpression left;

-    IExpression right;

-    left = GetComparisonExpression();

-    while (true) {

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case IS:

-      case 28:

-      case 29:

-        ;

-        break;

-      default:

-        goto label_3;

-      }

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case 28:

-        mcc_consume_token(28);

-        right = GetComparisonExpression();

-                left = ComparisonExpression.CreateEqual(left, right);

-        break;

-      case 29:

-        mcc_consume_token(29);

-        right = GetComparisonExpression();

-                left = ComparisonExpression.CreateNotEqual(left, right);

-        break;

-      default:

-        if (mcc_2_1(2)) {

-          mcc_consume_token(IS);

-          mcc_consume_token(NULL);

-                left = ComparisonExpression.CreateIsNull(left);

-        } else {

-          switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-          case IS:

-            mcc_consume_token(IS);

-            mcc_consume_token(NOT);

-            mcc_consume_token(NULL);

-                left = ComparisonExpression.CreateIsNotNull(left);

-            break;

-          default:

-            mcc_consume_token(-1);

-            throw new ParseException();

-          }

-        }

-        break;

-      }

-    }label_3: ;

-    

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public IExpression GetComparisonExpression() {

-    IExpression left;

-    IExpression right;

-    IExpression low;

-    IExpression high;

-    string t;

-    string u;

-        ArrayList list;

-    left = GetAddExpression();

-    while (true) {

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case NOT:

-      case BETWEEN:

-      case LIKE:

-      case IN:

-      case 30:

-      case 31:

-      case 32:

-      case 33:

-        ;

-        break;

-      default:

-        goto label_4;

-      }

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case 30:

-        mcc_consume_token(30);

-        right = GetAddExpression();

-                    left = ComparisonExpression.CreateGreaterThan(left, right);

-        break;

-      case 31:

-        mcc_consume_token(31);

-        right = GetAddExpression();

-                    left = ComparisonExpression.CreateGreaterThanOrEqual(left, right);

-        break;

-      case 32:

-        mcc_consume_token(32);

-        right = GetAddExpression();

-                    left = ComparisonExpression.CreateLesserThan(left, right);

-        break;

-      case 33:

-        mcc_consume_token(33);

-        right = GetAddExpression();

-                    left = ComparisonExpression.CreateLesserThanOrEqual(left, right);

-        break;

-      case LIKE:

-                                        u = null;

-        mcc_consume_token(LIKE);

-        t = GetStringLitteral();

-        switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-        case ESCAPE:

-          mcc_consume_token(ESCAPE);

-          u = GetStringLitteral();

-          break;

-        default:

-          ;

-          break;

-        }

-                    left = ComparisonExpression.CreateLike(left, t, u);

-        break;

-      default:

-        if (mcc_2_2(2)) {

-                                        u=null;

-          mcc_consume_token(NOT);

-          mcc_consume_token(LIKE);

-          t = GetStringLitteral();

-          switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-          case ESCAPE:

-            mcc_consume_token(ESCAPE);

-            u = GetStringLitteral();

-            break;

-          default:

-            ;

-            break;

-          }

-                    left = ComparisonExpression.CreateNotLike(left, t, u);

-        } else {

-          switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-          case BETWEEN:

-            mcc_consume_token(BETWEEN);

-            low = GetAddExpression();

-            mcc_consume_token(AND);

-            high = GetAddExpression();

-                                        left = ComparisonExpression.CreateBetween(left, low, high);

-            break;

-          default:

-            if (mcc_2_3(2)) {

-              mcc_consume_token(NOT);

-              mcc_consume_token(BETWEEN);

-              low = GetAddExpression();

-              mcc_consume_token(AND);

-              high = GetAddExpression();

-                                        left = ComparisonExpression.CreateNotBetween(left, low, high);

-            } else {

-              switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-              case IN:

-                mcc_consume_token(IN);

-                mcc_consume_token(34);

-                t = GetStringLitteral();

-                                    list = new ArrayList();

-                                    list.Add(t);

-                while (true) {

-                  switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-                  case 35:

-                    ;

-                    break;

-                  default:

-                    goto label_5;

-                  }

-                  mcc_consume_token(35);

-                  t = GetStringLitteral();

-                                            list.Add(t);

-                }label_5: ;

-                

-                mcc_consume_token(36);

-                           left = ComparisonExpression.CreateIn(left, list);

-                break;

-              default:

-                if (mcc_2_4(2)) {

-                  mcc_consume_token(NOT);

-                  mcc_consume_token(IN);

-                  mcc_consume_token(34);

-                  t = GetStringLitteral();

-                                    list = new ArrayList();

-                                    list.Add(t);

-                  while (true) {

-                    switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-                    case 35:

-                      ;

-                      break;

-                    default:

-                      goto label_6;

-                    }

-                    mcc_consume_token(35);

-                    t = GetStringLitteral();

-                                            list.Add(t);

-                  }label_6: ;

-                  

-                  mcc_consume_token(36);

-                           left = ComparisonExpression.CreateNotIn(left, list);

-                } else {

-                  mcc_consume_token(-1);

-                  throw new ParseException();

-                }

-                break;

-              }

-            }

-            break;

-          }

-        }

-        break;

-      }

-    }label_4: ;

-    

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public IExpression GetAddExpression() {

-    IExpression left;

-    IExpression right;

-    left = GetMultiplyExpression();

-    while (true) {

-      if (mcc_2_5(2147483647)) {

-        ;

-      } else {

-        goto label_7;

-      }

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case 37:

-        mcc_consume_token(37);

-        right = GetMultiplyExpression();

-                    left = ArithmeticExpression.CreatePlus(left, right);

-        break;

-      case 38:

-        mcc_consume_token(38);

-        right = GetMultiplyExpression();

-                    left = ArithmeticExpression.CreateMinus(left, right);

-        break;

-      default:

-        mcc_consume_token(-1);

-        throw new ParseException();

-      }

-    }label_7: ;

-    

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public IExpression GetMultiplyExpression() {

-    IExpression left;

-    IExpression right;

-    left = GetUnaryExpression();

-    while (true) {

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case 39:

-      case 40:

-      case 41:

-        ;

-        break;

-      default:

-        goto label_8;

-      }

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case 39:

-        mcc_consume_token(39);

-        right = GetUnaryExpression();

-                left = ArithmeticExpression.CreateMultiply(left, right);

-        break;

-      case 40:

-        mcc_consume_token(40);

-        right = GetUnaryExpression();

-                left = ArithmeticExpression.CreateDivide(left, right);

-        break;

-      case 41:

-        mcc_consume_token(41);

-        right = GetUnaryExpression();

-                left = ArithmeticExpression.CreateMod(left, right);

-        break;

-      default:

-        mcc_consume_token(-1);

-        throw new ParseException();

-      }

-    }label_8: ;

-    

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public IExpression GetUnaryExpression() {

-    IExpression left = null;

-    if (mcc_2_6(2147483647)) {

-      mcc_consume_token(37);

-      left = GetUnaryExpression();

-    } else {

-      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-      case 38:

-        mcc_consume_token(38);

-        left = GetUnaryExpression();

-                left = UnaryExpression.CreateNegate(left);

-        break;

-      case NOT:

-        mcc_consume_token(NOT);

-        left = GetUnaryExpression();

-                    left = UnaryExpression.CreateNOT(AsBooleanExpression(left));

-        break;

-      case TRUE:

-      case FALSE:

-      case NULL:

-      case DECIMAL_LITERAL:

-      case HEX_LITERAL:

-      case OCTAL_LITERAL:

-      case FLOATING_POINT_LITERAL:

-      case STRING_LITERAL:

-      case ID:

-      case 34:

-        left = GetPrimaryExpression();

-        break;

-      default:

-        mcc_consume_token(-1);

-        throw new ParseException();

-      }

-    }

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public IExpression GetPrimaryExpression() {

-    IExpression left = null;

-    switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-    case TRUE:

-    case FALSE:

-    case NULL:

-    case DECIMAL_LITERAL:

-    case HEX_LITERAL:

-    case OCTAL_LITERAL:

-    case FLOATING_POINT_LITERAL:

-    case STRING_LITERAL:

-      left = GetLiteral();

-      break;

-    case ID:

-      left = GetVariable();

-      break;

-    case 34:

-      mcc_consume_token(34);

-      left = GetOrExpression();

-      mcc_consume_token(36);

-      break;

-    default:

-      mcc_consume_token(-1);

-      throw new ParseException();

-    }

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public ConstantExpression GetLiteral() {

-    Token t;

-    string s;

-    ConstantExpression left = null;

-    switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {

-    case STRING_LITERAL:

-      s = GetStringLitteral();

-                left = new ConstantExpression(s);

-      break;

-    case DECIMAL_LITERAL:

-      t = mcc_consume_token(DECIMAL_LITERAL);

-                left = ConstantExpression.CreateFromDecimal(t.image);

-      break;

-    case HEX_LITERAL:

-      t = mcc_consume_token(HEX_LITERAL);

-                left = ConstantExpression.CreateFromHex(t.image);

-      break;

-    case OCTAL_LITERAL:

-      t = mcc_consume_token(OCTAL_LITERAL);

-                left = ConstantExpression.CreateFromOctal(t.image);

-      break;

-    case FLOATING_POINT_LITERAL:

-      t = mcc_consume_token(FLOATING_POINT_LITERAL);

-                left = ConstantExpression.CreateFloat(t.image);

-      break;

-    case TRUE:

-      mcc_consume_token(TRUE);

-                left = ConstantExpression.TRUE;

-      break;

-    case FALSE:

-      mcc_consume_token(FALSE);

-                left = ConstantExpression.FALSE;

-      break;

-    case NULL:

-      mcc_consume_token(NULL);

-                left = ConstantExpression.NULL;

-      break;

-    default:

-      mcc_consume_token(-1);

-      throw new ParseException();

-    }

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public string GetStringLitteral() {

-    Token t;

-    StringBuilder rc = new StringBuilder();

-    t = mcc_consume_token(STRING_LITERAL);

-        // Decode the sting value.

-        String image = t.image;

-        for(int c = 1; c < image.Length - 1; c++)

-        {

-                char ch = image[c];

-                if(ch == '\'')

-            {

-                        c++;

-            }

-                        rc.Append(ch);

-        }

-            {return rc.ToString();}

-    throw new Exception("Missing return statement in function");

-  }

-

-  public PropertyExpression GetVariable() {

-    Token t;

-    PropertyExpression left = null;

-    t = mcc_consume_token(ID);

-            left = new PropertyExpression(t.image);

-        {return left;}

-    throw new Exception("Missing return statement in function");

-  }

-

-  private bool mcc_2_1(int xla) {

-    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;

-    try { return !mcc_3_1(); }

-    catch(LookaheadSuccess) { return true; }

-  }

-

-  private bool mcc_2_2(int xla) {

-    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;

-    try { return !mcc_3_2(); }

-    catch(LookaheadSuccess) { return true; }

-  }

-

-  private bool mcc_2_3(int xla) {

-    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;

-    try { return !mcc_3_3(); }

-    catch(LookaheadSuccess) { return true; }

-  }

-

-  private bool mcc_2_4(int xla) {

-    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;

-    try { return !mcc_3_4(); }

-    catch(LookaheadSuccess) { return true; }

-  }

-

-  private bool mcc_2_5(int xla) {

-    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;

-    try { return !mcc_3_5(); }

-    catch(LookaheadSuccess) { return true; }

-  }

-

-  private bool mcc_2_6(int xla) {

-    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;

-    try { return !mcc_3_6(); }

-    catch(LookaheadSuccess) { return true; }

-  }

-

-  private bool mcc_3R_57() {

-    if (mcc_scan_token(ESCAPE)) return true;

-    if (mcc_3R_36()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_19() {

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_20()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_21()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_22()) return true;

-    }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_39() {

-    if (mcc_3R_41()) return true;

-    Token xsp;

-    while (true) {

-      xsp = mcc_scanpos;

-      if (mcc_3R_42()) { mcc_scanpos = xsp; break; }

-    }

-    return false;

-  }

-

-  private bool mcc_3_4() {

-    if (mcc_scan_token(NOT)) return true;

-    if (mcc_scan_token(IN)) return true;

-    if (mcc_scan_token(34)) return true;

-    if (mcc_3R_36()) return true;

-    Token xsp;

-    while (true) {

-      xsp = mcc_scanpos;

-      if (mcc_3R_59()) { mcc_scanpos = xsp; break; }

-    }

-    if (mcc_scan_token(36)) return true;

-    return false;

-  }

-

-  private bool mcc_3_6() {

-    if (mcc_scan_token(37)) return true;

-    if (mcc_3R_10()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_15() {

-    if (mcc_3R_19()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_36() {

-    if (mcc_scan_token(STRING_LITERAL)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_14() {

-    if (mcc_scan_token(NOT)) return true;

-    if (mcc_3R_10()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_12() {

-    if (mcc_scan_token(37)) return true;

-    if (mcc_3R_10()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_53() {

-    if (mcc_scan_token(IN)) return true;

-    if (mcc_scan_token(34)) return true;

-    if (mcc_3R_36()) return true;

-    Token xsp;

-    while (true) {

-      xsp = mcc_scanpos;

-      if (mcc_3R_58()) { mcc_scanpos = xsp; break; }

-    }

-    if (mcc_scan_token(36)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_45() {

-    if (mcc_scan_token(IS)) return true;

-    if (mcc_scan_token(NOT)) return true;

-    if (mcc_scan_token(NULL)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_13() {

-    if (mcc_scan_token(38)) return true;

-    if (mcc_3R_10()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_33() {

-    if (mcc_scan_token(NULL)) return true;

-    return false;

-  }

-

-  private bool mcc_3_1() {

-    if (mcc_scan_token(IS)) return true;

-    if (mcc_scan_token(NULL)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_10() {

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_12()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_13()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_14()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_15()) return true;

-    }

-    }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_44() {

-    if (mcc_scan_token(29)) return true;

-    if (mcc_3R_39()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_32() {

-    if (mcc_scan_token(FALSE)) return true;

-    return false;

-  }

-

-  private bool mcc_3_3() {

-    if (mcc_scan_token(NOT)) return true;

-    if (mcc_scan_token(BETWEEN)) return true;

-    if (mcc_3R_41()) return true;

-    if (mcc_scan_token(AND)) return true;

-    if (mcc_3R_41()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_43() {

-    if (mcc_scan_token(28)) return true;

-    if (mcc_3R_39()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_40() {

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_43()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_44()) {

-    mcc_scanpos = xsp;

-    if (mcc_3_1()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_45()) return true;

-    }

-    }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_52() {

-    if (mcc_scan_token(BETWEEN)) return true;

-    if (mcc_3R_41()) return true;

-    if (mcc_scan_token(AND)) return true;

-    if (mcc_3R_41()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_31() {

-    if (mcc_scan_token(TRUE)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_56() {

-    if (mcc_scan_token(ESCAPE)) return true;

-    if (mcc_3R_36()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_18() {

-    if (mcc_scan_token(41)) return true;

-    if (mcc_3R_10()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_30() {

-    if (mcc_scan_token(FLOATING_POINT_LITERAL)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_37() {

-    if (mcc_3R_39()) return true;

-    Token xsp;

-    while (true) {

-      xsp = mcc_scanpos;

-      if (mcc_3R_40()) { mcc_scanpos = xsp; break; }

-    }

-    return false;

-  }

-

-  private bool mcc_3_2() {

-    if (mcc_scan_token(NOT)) return true;

-    if (mcc_scan_token(LIKE)) return true;

-    if (mcc_3R_36()) return true;

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_57()) mcc_scanpos = xsp;

-    return false;

-  }

-

-  private bool mcc_3R_51() {

-    if (mcc_scan_token(LIKE)) return true;

-    if (mcc_3R_36()) return true;

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_56()) mcc_scanpos = xsp;

-    return false;

-  }

-

-  private bool mcc_3R_17() {

-    if (mcc_scan_token(40)) return true;

-    if (mcc_3R_10()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_29() {

-    if (mcc_scan_token(OCTAL_LITERAL)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_16() {

-    if (mcc_scan_token(39)) return true;

-    if (mcc_3R_10()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_11() {

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_16()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_17()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_18()) return true;

-    }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_38() {

-    if (mcc_scan_token(AND)) return true;

-    if (mcc_3R_37()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_28() {

-    if (mcc_scan_token(HEX_LITERAL)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_9() {

-    if (mcc_3R_10()) return true;

-    Token xsp;

-    while (true) {

-      xsp = mcc_scanpos;

-      if (mcc_3R_11()) { mcc_scanpos = xsp; break; }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_27() {

-    if (mcc_scan_token(DECIMAL_LITERAL)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_55() {

-    if (mcc_scan_token(38)) return true;

-    if (mcc_3R_9()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_34() {

-    if (mcc_3R_37()) return true;

-    Token xsp;

-    while (true) {

-      xsp = mcc_scanpos;

-      if (mcc_3R_38()) { mcc_scanpos = xsp; break; }

-    }

-    return false;

-  }

-

-  private bool mcc_3_5() {

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_scan_token(37)) {

-    mcc_scanpos = xsp;

-    if (mcc_scan_token(38)) return true;

-    }

-    if (mcc_3R_9()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_50() {

-    if (mcc_scan_token(33)) return true;

-    if (mcc_3R_41()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_54() {

-    if (mcc_scan_token(37)) return true;

-    if (mcc_3R_9()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_26() {

-    if (mcc_3R_36()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_49() {

-    if (mcc_scan_token(32)) return true;

-    if (mcc_3R_41()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_59() {

-    if (mcc_scan_token(35)) return true;

-    if (mcc_3R_36()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_46() {

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_54()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_55()) return true;

-    }

-    return false;

-  }

-

-  private bool mcc_3R_35() {

-    if (mcc_scan_token(OR)) return true;

-    if (mcc_3R_34()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_23() {

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_26()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_27()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_28()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_29()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_30()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_31()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_32()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_33()) return true;

-    }

-    }

-    }

-    }

-    }

-    }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_48() {

-    if (mcc_scan_token(31)) return true;

-    if (mcc_3R_41()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_24() {

-    if (mcc_scan_token(ID)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_47() {

-    if (mcc_scan_token(30)) return true;

-    if (mcc_3R_41()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_42() {

-    Token xsp;

-    xsp = mcc_scanpos;

-    if (mcc_3R_47()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_48()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_49()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_50()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_51()) {

-    mcc_scanpos = xsp;

-    if (mcc_3_2()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_52()) {

-    mcc_scanpos = xsp;

-    if (mcc_3_3()) {

-    mcc_scanpos = xsp;

-    if (mcc_3R_53()) {

-    mcc_scanpos = xsp;

-    if (mcc_3_4()) return true;

-    }

-    }

-    }

-    }

-    }

-    }

-    }

-    }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_41() {

-    if (mcc_3R_9()) return true;

-    Token xsp;

-    while (true) {

-      xsp = mcc_scanpos;

-      if (mcc_3R_46()) { mcc_scanpos = xsp; break; }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_25() {

-    if (mcc_3R_34()) return true;

-    Token xsp;

-    while (true) {

-      xsp = mcc_scanpos;

-      if (mcc_3R_35()) { mcc_scanpos = xsp; break; }

-    }

-    return false;

-  }

-

-  private bool mcc_3R_22() {

-    if (mcc_scan_token(34)) return true;

-    if (mcc_3R_25()) return true;

-    if (mcc_scan_token(36)) return true;

-    return false;

-  }

-

-  private bool mcc_3R_21() {

-    if (mcc_3R_24()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_20() {

-    if (mcc_3R_23()) return true;

-    return false;

-  }

-

-  private bool mcc_3R_58() {

-    if (mcc_scan_token(35)) return true;

-    if (mcc_3R_36()) return true;

-    return false;

-  }

-

-  public SelectorParserTokenManager token_source;

-  SimpleCharStream mcc_input_stream;

-  public Token token, mcc_nt;

-  private int mcc_ntk;

-  private Token mcc_scanpos, mcc_lastpos;

-  private int mcc_la;

-  public bool lookingAhead = false;

-  //private bool mcc_semLA;

-

-  public SelectorParser(System.IO.Stream stream) {

-    mcc_input_stream = new SimpleCharStream(stream, 1, 1);

-    token_source = new SelectorParserTokenManager(mcc_input_stream);

-    token = new Token();

-    mcc_ntk = -1;

-  }

-

-  public void ReInit(System.IO.Stream stream) {

-    mcc_input_stream.ReInit(stream, 1, 1);

-    token_source.ReInit(mcc_input_stream);

-    token = new Token();

-    mcc_ntk = -1;

-  }

-

-  public SelectorParser(System.IO.TextReader stream) {

-    mcc_input_stream = new SimpleCharStream(stream, 1, 1);

-    token_source = new SelectorParserTokenManager(mcc_input_stream);

-    token = new Token();

-    mcc_ntk = -1;

-  }

-

-  public void ReInit(System.IO.TextReader stream) {

-    mcc_input_stream.ReInit(stream, 1, 1);

-    token_source.ReInit(mcc_input_stream);

-    token = new Token();

-    mcc_ntk = -1;

-  }

-

-  public SelectorParser(SelectorParserTokenManager tm) {

-    token_source = tm;

-    token = new Token();

-    mcc_ntk = -1;

-  }

-

-  public void ReInit(SelectorParserTokenManager tm) {

-    token_source = tm;

-    token = new Token();

-    mcc_ntk = -1;

-  }

-

-   private Token mcc_consume_token(int kind) {

-    Token oldToken = null;

-    if ((oldToken = token).next != null) token = token.next;

-    else token = token.next = token_source.GetNextToken();

-    mcc_ntk = -1;

-    if (token.kind == kind) {

-      return token;

-    }

-    token = oldToken;

-    throw GenerateParseException();

-  }

-

-  private class LookaheadSuccess : System.Exception { }

-  private LookaheadSuccess mcc_ls = new LookaheadSuccess();

-  private bool mcc_scan_token(int kind) {

-    if (mcc_scanpos == mcc_lastpos) {

-      mcc_la--;

-      if (mcc_scanpos.next == null) {

-        mcc_lastpos = mcc_scanpos = mcc_scanpos.next = token_source.GetNextToken();

-      } else {

-        mcc_lastpos = mcc_scanpos = mcc_scanpos.next;

-      }

-    } else {

-      mcc_scanpos = mcc_scanpos.next;

-    }

-    if (mcc_scanpos.kind != kind) return true;

-    if (mcc_la == 0 && mcc_scanpos == mcc_lastpos) throw mcc_ls;

-    return false;

-  }

-

-  public Token GetNextToken() {

-    if (token.next != null) token = token.next;

-    else token = token.next = token_source.GetNextToken();

-    mcc_ntk = -1;

-    return token;

-  }

-

-  public Token GetToken(int index) {

-    Token t = lookingAhead ? mcc_scanpos : token;

-    for (int i = 0; i < index; i++) {

-      if (t.next != null) t = t.next;

-      else t = t.next = token_source.GetNextToken();

-    }

-    return t;

-  }

-

-  private int mcc_mntk() {

-    if ((mcc_nt=token.next) == null)

-      return (mcc_ntk = (token.next=token_source.GetNextToken()).kind);

-    else

-      return (mcc_ntk = mcc_nt.kind);

-  }

-

-  public ParseException GenerateParseException() {

-    Token errortok = token.next;

-    int line = errortok.beginLine, column = errortok.beginColumn;

-    string mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image;

-    return new ParseException("Parse error at line " + line + ", column " + column + ".  Encountered: " + mess);

-  }

-

-  public void enable_tracing() {

-  }

-

-  public void disable_tracing() {

-  }

-

-}

-

+/* Generated By:CSharpCC: Do not edit this line. SelectorParser.cs */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.IO;
+using System.Text;
+using System.Collections;
+
+using Apache.NMS;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// JMS Selector Parser generated by <a href="https://github.com/deveel/csharpcc">CSharpCC</a>
+    /// 
+    /// Do not edit this .cs file directly - it is autogenerated from SelectorParser.csc
+    /// using <c>csharpcc.exe -UNICODE_INPUT=true SelectorParser.csc</c>.
+    /// 
+    /// SelectorParser.csc is adapted from
+    /// <a href="https://raw.githubusercontent.com/apache/activemq/activemq-4.0/activemq-core/src/main/grammar/SelectorParser.jj">
+    /// ActiveMQ 4.0 SelectorParser.jj</a>
+    /// </summary>
+    public class SelectorParser : SelectorParserConstants {
+
+        public SelectorParser()
+            : this(new StringReader(""))
+        {
+        }
+
+        public IBooleanExpression Parse(string selector)
+        {
+            this.ReInit(new StringReader(selector));
+
+            try
+            {
+                return this.JmsSelector();
+            }
+            catch(Exception e)
+            {
+                    throw new InvalidSelectorException(selector, e);
+            }
+        }
+
+        private IBooleanExpression AsBooleanExpression(IExpression value)
+        {
+            if(value is IBooleanExpression)
+            {
+                return (IBooleanExpression)value;
+            }
+            if(value is PropertyExpression)
+            {
+                return UnaryExpression.CreateBooleanCast(value);
+            }
+            throw new ParseException("IExpression will not result in a boolean value: " + value);
+        }
+
+// ----------------------------------------------------------------------------
+// Grammar
+// ----------------------------------------------------------------------------
+  public IBooleanExpression JmsSelector() {
+    IExpression left = null;
+    left = GetOrExpression();
+        {return AsBooleanExpression(left);}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public IExpression GetOrExpression() {
+    IExpression left;
+    IExpression right;
+    left = GetAndExpression();
+    while (true) {
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case OR:
+        ;
+        break;
+      default:
+        goto label_1;
+      }
+      mcc_consume_token(OR);
+      right = GetAndExpression();
+                left = LogicExpression.CreateOR(AsBooleanExpression(left), AsBooleanExpression(right));
+    }label_1: ;
+    
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public IExpression GetAndExpression() {
+    IExpression left;
+    IExpression right;
+    left = GetEqualityExpression();
+    while (true) {
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case AND:
+        ;
+        break;
+      default:
+        goto label_2;
+      }
+      mcc_consume_token(AND);
+      right = GetEqualityExpression();
+                left = LogicExpression.CreateAND(AsBooleanExpression(left), AsBooleanExpression(right));
+    }label_2: ;
+    
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public IExpression GetEqualityExpression() {
+    IExpression left;
+    IExpression right;
+    left = GetComparisonExpression();
+    while (true) {
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case IS:
+      case 28:
+      case 29:
+        ;
+        break;
+      default:
+        goto label_3;
+      }
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case 28:
+        mcc_consume_token(28);
+        right = GetComparisonExpression();
+                left = ComparisonExpression.CreateEqual(left, right);
+        break;
+      case 29:
+        mcc_consume_token(29);
+        right = GetComparisonExpression();
+                left = ComparisonExpression.CreateNotEqual(left, right);
+        break;
+      default:
+        if (mcc_2_1(2)) {
+          mcc_consume_token(IS);
+          mcc_consume_token(NULL);
+                left = ComparisonExpression.CreateIsNull(left);
+        } else {
+          switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+          case IS:
+            mcc_consume_token(IS);
+            mcc_consume_token(NOT);
+            mcc_consume_token(NULL);
+                left = ComparisonExpression.CreateIsNotNull(left);
+            break;
+          default:
+            mcc_consume_token(-1);
+            throw new ParseException();
+          }
+        }
+        break;
+      }
+    }label_3: ;
+    
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public IExpression GetComparisonExpression() {
+    IExpression left;
+    IExpression right;
+    IExpression low;
+    IExpression high;
+    string t;
+    string u;
+        ArrayList list;
+    left = GetAddExpression();
+    while (true) {
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case NOT:
+      case BETWEEN:
+      case LIKE:
+      case IN:
+      case 30:
+      case 31:
+      case 32:
+      case 33:
+        ;
+        break;
+      default:
+        goto label_4;
+      }
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case 30:
+        mcc_consume_token(30);
+        right = GetAddExpression();
+                    left = ComparisonExpression.CreateGreaterThan(left, right);
+        break;
+      case 31:
+        mcc_consume_token(31);
+        right = GetAddExpression();
+                    left = ComparisonExpression.CreateGreaterThanOrEqual(left, right);
+        break;
+      case 32:
+        mcc_consume_token(32);
+        right = GetAddExpression();
+                    left = ComparisonExpression.CreateLesserThan(left, right);
+        break;
+      case 33:
+        mcc_consume_token(33);
+        right = GetAddExpression();
+                    left = ComparisonExpression.CreateLesserThanOrEqual(left, right);
+        break;
+      case LIKE:
+                                        u = null;
+        mcc_consume_token(LIKE);
+        t = GetStringLitteral();
+        switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+        case ESCAPE:
+          mcc_consume_token(ESCAPE);
+          u = GetStringLitteral();
+          break;
+        default:
+          ;
+          break;
+        }
+                    left = ComparisonExpression.CreateLike(left, t, u);
+        break;
+      default:
+        if (mcc_2_2(2)) {
+                                        u=null;
+          mcc_consume_token(NOT);
+          mcc_consume_token(LIKE);
+          t = GetStringLitteral();
+          switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+          case ESCAPE:
+            mcc_consume_token(ESCAPE);
+            u = GetStringLitteral();
+            break;
+          default:
+            ;
+            break;
+          }
+                    left = ComparisonExpression.CreateNotLike(left, t, u);
+        } else {
+          switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+          case BETWEEN:
+            mcc_consume_token(BETWEEN);
+            low = GetAddExpression();
+            mcc_consume_token(AND);
+            high = GetAddExpression();
+                                        left = ComparisonExpression.CreateBetween(left, low, high);
+            break;
+          default:
+            if (mcc_2_3(2)) {
+              mcc_consume_token(NOT);
+              mcc_consume_token(BETWEEN);
+              low = GetAddExpression();
+              mcc_consume_token(AND);
+              high = GetAddExpression();
+                                        left = ComparisonExpression.CreateNotBetween(left, low, high);
+            } else {
+              switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+              case IN:
+                mcc_consume_token(IN);
+                mcc_consume_token(34);
+                t = GetStringLitteral();
+                                    list = new ArrayList();
+                                    list.Add(t);
+                while (true) {
+                  switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+                  case 35:
+                    ;
+                    break;
+                  default:
+                    goto label_5;
+                  }
+                  mcc_consume_token(35);
+                  t = GetStringLitteral();
+                                            list.Add(t);
+                }label_5: ;
+                
+                mcc_consume_token(36);
+                           left = ComparisonExpression.CreateIn(left, list);
+                break;
+              default:
+                if (mcc_2_4(2)) {
+                  mcc_consume_token(NOT);
+                  mcc_consume_token(IN);
+                  mcc_consume_token(34);
+                  t = GetStringLitteral();
+                                    list = new ArrayList();
+                                    list.Add(t);
+                  while (true) {
+                    switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+                    case 35:
+                      ;
+                      break;
+                    default:
+                      goto label_6;
+                    }
+                    mcc_consume_token(35);
+                    t = GetStringLitteral();
+                                            list.Add(t);
+                  }label_6: ;
+                  
+                  mcc_consume_token(36);
+                           left = ComparisonExpression.CreateNotIn(left, list);
+                } else {
+                  mcc_consume_token(-1);
+                  throw new ParseException();
+                }
+                break;
+              }
+            }
+            break;
+          }
+        }
+        break;
+      }
+    }label_4: ;
+    
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public IExpression GetAddExpression() {
+    IExpression left;
+    IExpression right;
+    left = GetMultiplyExpression();
+    while (true) {
+      if (mcc_2_5(2147483647)) {
+        ;
+      } else {
+        goto label_7;
+      }
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case 37:
+        mcc_consume_token(37);
+        right = GetMultiplyExpression();
+                    left = ArithmeticExpression.CreatePlus(left, right);
+        break;
+      case 38:
+        mcc_consume_token(38);
+        right = GetMultiplyExpression();
+                    left = ArithmeticExpression.CreateMinus(left, right);
+        break;
+      default:
+        mcc_consume_token(-1);
+        throw new ParseException();
+      }
+    }label_7: ;
+    
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public IExpression GetMultiplyExpression() {
+    IExpression left;
+    IExpression right;
+    left = GetUnaryExpression();
+    while (true) {
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case 39:
+      case 40:
+      case 41:
+        ;
+        break;
+      default:
+        goto label_8;
+      }
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case 39:
+        mcc_consume_token(39);
+        right = GetUnaryExpression();
+                left = ArithmeticExpression.CreateMultiply(left, right);
+        break;
+      case 40:
+        mcc_consume_token(40);
+        right = GetUnaryExpression();
+                left = ArithmeticExpression.CreateDivide(left, right);
+        break;
+      case 41:
+        mcc_consume_token(41);
+        right = GetUnaryExpression();
+                left = ArithmeticExpression.CreateMod(left, right);
+        break;
+      default:
+        mcc_consume_token(-1);
+        throw new ParseException();
+      }
+    }label_8: ;
+    
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public IExpression GetUnaryExpression() {
+    IExpression left = null;
+    if (mcc_2_6(2147483647)) {
+      mcc_consume_token(37);
+      left = GetUnaryExpression();
+    } else {
+      switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+      case 38:
+        mcc_consume_token(38);
+        left = GetUnaryExpression();
+                left = UnaryExpression.CreateNegate(left);
+        break;
+      case NOT:
+        mcc_consume_token(NOT);
+        left = GetUnaryExpression();
+                    left = UnaryExpression.CreateNOT(AsBooleanExpression(left));
+        break;
+      case TRUE:
+      case FALSE:
+      case NULL:
+      case DECIMAL_LITERAL:
+      case HEX_LITERAL:
+      case OCTAL_LITERAL:
+      case FLOATING_POINT_LITERAL:
+      case STRING_LITERAL:
+      case ID:
+      case 34:
+        left = GetPrimaryExpression();
+        break;
+      default:
+        mcc_consume_token(-1);
+        throw new ParseException();
+      }
+    }
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public IExpression GetPrimaryExpression() {
+    IExpression left = null;
+    switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+    case TRUE:
+    case FALSE:
+    case NULL:
+    case DECIMAL_LITERAL:
+    case HEX_LITERAL:
+    case OCTAL_LITERAL:
+    case FLOATING_POINT_LITERAL:
+    case STRING_LITERAL:
+      left = GetLiteral();
+      break;
+    case ID:
+      left = GetVariable();
+      break;
+    case 34:
+      mcc_consume_token(34);
+      left = GetOrExpression();
+      mcc_consume_token(36);
+      break;
+    default:
+      mcc_consume_token(-1);
+      throw new ParseException();
+    }
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public ConstantExpression GetLiteral() {
+    Token t;
+    string s;
+    ConstantExpression left = null;
+    switch ((mcc_ntk==-1)?mcc_mntk():mcc_ntk) {
+    case STRING_LITERAL:
+      s = GetStringLitteral();
+                left = new ConstantExpression(s);
+      break;
+    case DECIMAL_LITERAL:
+      t = mcc_consume_token(DECIMAL_LITERAL);
+                left = ConstantExpression.CreateFromDecimal(t.image);
+      break;
+    case HEX_LITERAL:
+      t = mcc_consume_token(HEX_LITERAL);
+                left = ConstantExpression.CreateFromHex(t.image);
+      break;
+    case OCTAL_LITERAL:
+      t = mcc_consume_token(OCTAL_LITERAL);
+                left = ConstantExpression.CreateFromOctal(t.image);
+      break;
+    case FLOATING_POINT_LITERAL:
+      t = mcc_consume_token(FLOATING_POINT_LITERAL);
+                left = ConstantExpression.CreateFloat(t.image);
+      break;
+    case TRUE:
+      mcc_consume_token(TRUE);
+                left = ConstantExpression.TRUE;
+      break;
+    case FALSE:
+      mcc_consume_token(FALSE);
+                left = ConstantExpression.FALSE;
+      break;
+    case NULL:
+      mcc_consume_token(NULL);
+                left = ConstantExpression.NULL;
+      break;
+    default:
+      mcc_consume_token(-1);
+      throw new ParseException();
+    }
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public string GetStringLitteral() {
+    Token t;
+    StringBuilder rc = new StringBuilder();
+    t = mcc_consume_token(STRING_LITERAL);
+        // Decode the sting value.
+        String image = t.image;
+        for(int c = 1; c < image.Length - 1; c++)
+        {
+                char ch = image[c];
+                if(ch == '\'')
+            {
+                        c++;
+            }
+                        rc.Append(ch);
+        }
+            {return rc.ToString();}
+    throw new Exception("Missing return statement in function");
+  }
+
+  public PropertyExpression GetVariable() {
+    Token t;
+    PropertyExpression left = null;
+    t = mcc_consume_token(ID);
+            left = new PropertyExpression(t.image);
+        {return left;}
+    throw new Exception("Missing return statement in function");
+  }
+
+  private bool mcc_2_1(int xla) {
+    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;
+    try { return !mcc_3_1(); }
+    catch(LookaheadSuccess) { return true; }
+  }
+
+  private bool mcc_2_2(int xla) {
+    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;
+    try { return !mcc_3_2(); }
+    catch(LookaheadSuccess) { return true; }
+  }
+
+  private bool mcc_2_3(int xla) {
+    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;
+    try { return !mcc_3_3(); }
+    catch(LookaheadSuccess) { return true; }
+  }
+
+  private bool mcc_2_4(int xla) {
+    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;
+    try { return !mcc_3_4(); }
+    catch(LookaheadSuccess) { return true; }
+  }
+
+  private bool mcc_2_5(int xla) {
+    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;
+    try { return !mcc_3_5(); }
+    catch(LookaheadSuccess) { return true; }
+  }
+
+  private bool mcc_2_6(int xla) {
+    mcc_la = xla; mcc_lastpos = mcc_scanpos = token;
+    try { return !mcc_3_6(); }
+    catch(LookaheadSuccess) { return true; }
+  }
+
+  private bool mcc_3R_57() {
+    if (mcc_scan_token(ESCAPE)) return true;
+    if (mcc_3R_36()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_19() {
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_20()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_21()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_22()) return true;
+    }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_39() {
+    if (mcc_3R_41()) return true;
+    Token xsp;
+    while (true) {
+      xsp = mcc_scanpos;
+      if (mcc_3R_42()) { mcc_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private bool mcc_3_4() {
+    if (mcc_scan_token(NOT)) return true;
+    if (mcc_scan_token(IN)) return true;
+    if (mcc_scan_token(34)) return true;
+    if (mcc_3R_36()) return true;
+    Token xsp;
+    while (true) {
+      xsp = mcc_scanpos;
+      if (mcc_3R_59()) { mcc_scanpos = xsp; break; }
+    }
+    if (mcc_scan_token(36)) return true;
+    return false;
+  }
+
+  private bool mcc_3_6() {
+    if (mcc_scan_token(37)) return true;
+    if (mcc_3R_10()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_15() {
+    if (mcc_3R_19()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_36() {
+    if (mcc_scan_token(STRING_LITERAL)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_14() {
+    if (mcc_scan_token(NOT)) return true;
+    if (mcc_3R_10()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_12() {
+    if (mcc_scan_token(37)) return true;
+    if (mcc_3R_10()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_53() {
+    if (mcc_scan_token(IN)) return true;
+    if (mcc_scan_token(34)) return true;
+    if (mcc_3R_36()) return true;
+    Token xsp;
+    while (true) {
+      xsp = mcc_scanpos;
+      if (mcc_3R_58()) { mcc_scanpos = xsp; break; }
+    }
+    if (mcc_scan_token(36)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_45() {
+    if (mcc_scan_token(IS)) return true;
+    if (mcc_scan_token(NOT)) return true;
+    if (mcc_scan_token(NULL)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_13() {
+    if (mcc_scan_token(38)) return true;
+    if (mcc_3R_10()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_33() {
+    if (mcc_scan_token(NULL)) return true;
+    return false;
+  }
+
+  private bool mcc_3_1() {
+    if (mcc_scan_token(IS)) return true;
+    if (mcc_scan_token(NULL)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_10() {
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_12()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_13()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_14()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_15()) return true;
+    }
+    }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_44() {
+    if (mcc_scan_token(29)) return true;
+    if (mcc_3R_39()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_32() {
+    if (mcc_scan_token(FALSE)) return true;
+    return false;
+  }
+
+  private bool mcc_3_3() {
+    if (mcc_scan_token(NOT)) return true;
+    if (mcc_scan_token(BETWEEN)) return true;
+    if (mcc_3R_41()) return true;
+    if (mcc_scan_token(AND)) return true;
+    if (mcc_3R_41()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_43() {
+    if (mcc_scan_token(28)) return true;
+    if (mcc_3R_39()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_40() {
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_43()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_44()) {
+    mcc_scanpos = xsp;
+    if (mcc_3_1()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_45()) return true;
+    }
+    }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_52() {
+    if (mcc_scan_token(BETWEEN)) return true;
+    if (mcc_3R_41()) return true;
+    if (mcc_scan_token(AND)) return true;
+    if (mcc_3R_41()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_31() {
+    if (mcc_scan_token(TRUE)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_56() {
+    if (mcc_scan_token(ESCAPE)) return true;
+    if (mcc_3R_36()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_18() {
+    if (mcc_scan_token(41)) return true;
+    if (mcc_3R_10()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_30() {
+    if (mcc_scan_token(FLOATING_POINT_LITERAL)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_37() {
+    if (mcc_3R_39()) return true;
+    Token xsp;
+    while (true) {
+      xsp = mcc_scanpos;
+      if (mcc_3R_40()) { mcc_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private bool mcc_3_2() {
+    if (mcc_scan_token(NOT)) return true;
+    if (mcc_scan_token(LIKE)) return true;
+    if (mcc_3R_36()) return true;
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_57()) mcc_scanpos = xsp;
+    return false;
+  }
+
+  private bool mcc_3R_51() {
+    if (mcc_scan_token(LIKE)) return true;
+    if (mcc_3R_36()) return true;
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_56()) mcc_scanpos = xsp;
+    return false;
+  }
+
+  private bool mcc_3R_17() {
+    if (mcc_scan_token(40)) return true;
+    if (mcc_3R_10()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_29() {
+    if (mcc_scan_token(OCTAL_LITERAL)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_16() {
+    if (mcc_scan_token(39)) return true;
+    if (mcc_3R_10()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_11() {
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_16()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_17()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_18()) return true;
+    }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_38() {
+    if (mcc_scan_token(AND)) return true;
+    if (mcc_3R_37()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_28() {
+    if (mcc_scan_token(HEX_LITERAL)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_9() {
+    if (mcc_3R_10()) return true;
+    Token xsp;
+    while (true) {
+      xsp = mcc_scanpos;
+      if (mcc_3R_11()) { mcc_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_27() {
+    if (mcc_scan_token(DECIMAL_LITERAL)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_55() {
+    if (mcc_scan_token(38)) return true;
+    if (mcc_3R_9()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_34() {
+    if (mcc_3R_37()) return true;
+    Token xsp;
+    while (true) {
+      xsp = mcc_scanpos;
+      if (mcc_3R_38()) { mcc_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private bool mcc_3_5() {
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_scan_token(37)) {
+    mcc_scanpos = xsp;
+    if (mcc_scan_token(38)) return true;
+    }
+    if (mcc_3R_9()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_50() {
+    if (mcc_scan_token(33)) return true;
+    if (mcc_3R_41()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_54() {
+    if (mcc_scan_token(37)) return true;
+    if (mcc_3R_9()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_26() {
+    if (mcc_3R_36()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_49() {
+    if (mcc_scan_token(32)) return true;
+    if (mcc_3R_41()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_59() {
+    if (mcc_scan_token(35)) return true;
+    if (mcc_3R_36()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_46() {
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_54()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_55()) return true;
+    }
+    return false;
+  }
+
+  private bool mcc_3R_35() {
+    if (mcc_scan_token(OR)) return true;
+    if (mcc_3R_34()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_23() {
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_26()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_27()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_28()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_29()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_30()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_31()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_32()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_33()) return true;
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_48() {
+    if (mcc_scan_token(31)) return true;
+    if (mcc_3R_41()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_24() {
+    if (mcc_scan_token(ID)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_47() {
+    if (mcc_scan_token(30)) return true;
+    if (mcc_3R_41()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_42() {
+    Token xsp;
+    xsp = mcc_scanpos;
+    if (mcc_3R_47()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_48()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_49()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_50()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_51()) {
+    mcc_scanpos = xsp;
+    if (mcc_3_2()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_52()) {
+    mcc_scanpos = xsp;
+    if (mcc_3_3()) {
+    mcc_scanpos = xsp;
+    if (mcc_3R_53()) {
+    mcc_scanpos = xsp;
+    if (mcc_3_4()) return true;
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_41() {
+    if (mcc_3R_9()) return true;
+    Token xsp;
+    while (true) {
+      xsp = mcc_scanpos;
+      if (mcc_3R_46()) { mcc_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_25() {
+    if (mcc_3R_34()) return true;
+    Token xsp;
+    while (true) {
+      xsp = mcc_scanpos;
+      if (mcc_3R_35()) { mcc_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private bool mcc_3R_22() {
+    if (mcc_scan_token(34)) return true;
+    if (mcc_3R_25()) return true;
+    if (mcc_scan_token(36)) return true;
+    return false;
+  }
+
+  private bool mcc_3R_21() {
+    if (mcc_3R_24()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_20() {
+    if (mcc_3R_23()) return true;
+    return false;
+  }
+
+  private bool mcc_3R_58() {
+    if (mcc_scan_token(35)) return true;
+    if (mcc_3R_36()) return true;
+    return false;
+  }
+
+  public SelectorParserTokenManager token_source;
+  SimpleCharStream mcc_input_stream;
+  public Token token, mcc_nt;
+  private int mcc_ntk;
+  private Token mcc_scanpos, mcc_lastpos;
+  private int mcc_la;
+  public bool lookingAhead = false;
+  //private bool mcc_semLA;
+
+  public SelectorParser(System.IO.Stream stream) {
+    mcc_input_stream = new SimpleCharStream(stream, 1, 1);
+    token_source = new SelectorParserTokenManager(mcc_input_stream);
+    token = new Token();
+    mcc_ntk = -1;
+  }
+
+  public void ReInit(System.IO.Stream stream) {
+    mcc_input_stream.ReInit(stream, 1, 1);
+    token_source.ReInit(mcc_input_stream);
+    token = new Token();
+    mcc_ntk = -1;
+  }
+
+  public SelectorParser(System.IO.TextReader stream) {
+    mcc_input_stream = new SimpleCharStream(stream, 1, 1);
+    token_source = new SelectorParserTokenManager(mcc_input_stream);
+    token = new Token();
+    mcc_ntk = -1;
+  }
+
+  public void ReInit(System.IO.TextReader stream) {
+    mcc_input_stream.ReInit(stream, 1, 1);
+    token_source.ReInit(mcc_input_stream);
+    token = new Token();
+    mcc_ntk = -1;
+  }
+
+  public SelectorParser(SelectorParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    mcc_ntk = -1;
+  }
+
+  public void ReInit(SelectorParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    mcc_ntk = -1;
+  }
+
+   private Token mcc_consume_token(int kind) {
+    Token oldToken = null;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.GetNextToken();
+    mcc_ntk = -1;
+    if (token.kind == kind) {
+      return token;
+    }
+    token = oldToken;
+    throw GenerateParseException();
+  }
+
+  private class LookaheadSuccess : System.Exception { }
+  private LookaheadSuccess mcc_ls = new LookaheadSuccess();
+  private bool mcc_scan_token(int kind) {
+    if (mcc_scanpos == mcc_lastpos) {
+      mcc_la--;
+      if (mcc_scanpos.next == null) {
+        mcc_lastpos = mcc_scanpos = mcc_scanpos.next = token_source.GetNextToken();
+      } else {
+        mcc_lastpos = mcc_scanpos = mcc_scanpos.next;
+      }
+    } else {
+      mcc_scanpos = mcc_scanpos.next;
+    }
+    if (mcc_scanpos.kind != kind) return true;
+    if (mcc_la == 0 && mcc_scanpos == mcc_lastpos) throw mcc_ls;
+    return false;
+  }
+
+  public Token GetNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.GetNextToken();
+    mcc_ntk = -1;
+    return token;
+  }
+
+  public Token GetToken(int index) {
+    Token t = lookingAhead ? mcc_scanpos : token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.GetNextToken();
+    }
+    return t;
+  }
+
+  private int mcc_mntk() {
+    if ((mcc_nt=token.next) == null)
+      return (mcc_ntk = (token.next=token_source.GetNextToken()).kind);
+    else
+      return (mcc_ntk = mcc_nt.kind);
+  }
+
+  public ParseException GenerateParseException() {
+    Token errortok = token.next;
+    int line = errortok.beginLine, column = errortok.beginColumn;
+    string mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image;
+    return new ParseException("Parse error at line " + line + ", column " + column + ".  Encountered: " + mess);
+  }
+
+  public void enable_tracing() {
+  }
+
+  public void disable_tracing() {
+  }
+
+}
+
 }
\ No newline at end of file
diff --git a/src/main/csharp/Selector/SelectorParser.csc b/src/main/csharp/Selector/SelectorParser.csc
index be05ab8..d7fa5c8 100644
--- a/src/main/csharp/Selector/SelectorParser.csc
+++ b/src/main/csharp/Selector/SelectorParser.csc
@@ -1,16 +1,15 @@
-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  * See the License for the specific language governing permissions and

  * limitations under the License.

diff --git a/src/main/csharp/Selector/SelectorParserConstants.cs b/src/main/csharp/Selector/SelectorParserConstants.cs
index 5f75539..74c5362 100644
--- a/src/main/csharp/Selector/SelectorParserConstants.cs
+++ b/src/main/csharp/Selector/SelectorParserConstants.cs
@@ -1,75 +1,75 @@
-/* Generated By:CSharpCC: Do not edit this line. SelectorParserConstants.cs */

-public  class SelectorParserConstants {

-

-  public const int EOF = 0;

-  public const int LINE_COMMENT = 6;

-  public const int BLOCK_COMMENT = 7;

-  public const int NOT = 8;

-  public const int AND = 9;

-  public const int OR = 10;

-  public const int BETWEEN = 11;

-  public const int LIKE = 12;

-  public const int ESCAPE = 13;

-  public const int IN = 14;

-  public const int IS = 15;

-  public const int TRUE = 16;

-  public const int FALSE = 17;

-  public const int NULL = 18;

-  public const int XPATH = 19;

-  public const int XQUERY = 20;

-  public const int DECIMAL_LITERAL = 21;

-  public const int HEX_LITERAL = 22;

-  public const int OCTAL_LITERAL = 23;

-  public const int FLOATING_POINT_LITERAL = 24;

-  public const int EXPONENT = 25;

-  public const int STRING_LITERAL = 26;

-  public const int ID = 27;

-

-  public const int DEFAULT = 0;

-

-  public readonly string[] tokenImage = {

-    "<EOF>",

-    "\" \"",

-    "\"\\t\"",

-    "\"\\n\"",

-    "\"\\r\"",

-    "\"\\f\"",

-    "<LINE_COMMENT>",

-    "<BLOCK_COMMENT>",

-    "\"NOT\"",

-    "\"AND\"",

-    "\"OR\"",

-    "\"BETWEEN\"",

-    "\"LIKE\"",

-    "\"ESCAPE\"",

-    "\"IN\"",

-    "\"IS\"",

-    "\"TRUE\"",

-    "\"FALSE\"",

-    "\"NULL\"",

-    "\"XPATH\"",

-    "\"XQUERY\"",

-    "<DECIMAL_LITERAL>",

-    "<HEX_LITERAL>",

-    "<OCTAL_LITERAL>",

-    "<FLOATING_POINT_LITERAL>",

-    "<EXPONENT>",

-    "<STRING_LITERAL>",

-    "<ID>",

-    "\"=\"",

-    "\"<>\"",

-    "\">\"",

-    "\">=\"",

-    "\"<\"",

-    "\"<=\"",

-    "\"(\"",

-    "\",\"",

-    "\")\"",

-    "\"+\"",

-    "\"-\"",

-    "\"*\"",

-    "\"/\"",

-    "\"%\"",

-  };

-

-}

+/* Generated By:CSharpCC: Do not edit this line. SelectorParserConstants.cs */
+public  class SelectorParserConstants {
+
+  public const int EOF = 0;
+  public const int LINE_COMMENT = 6;
+  public const int BLOCK_COMMENT = 7;
+  public const int NOT = 8;
+  public const int AND = 9;
+  public const int OR = 10;
+  public const int BETWEEN = 11;
+  public const int LIKE = 12;
+  public const int ESCAPE = 13;
+  public const int IN = 14;
+  public const int IS = 15;
+  public const int TRUE = 16;
+  public const int FALSE = 17;
+  public const int NULL = 18;
+  public const int XPATH = 19;
+  public const int XQUERY = 20;
+  public const int DECIMAL_LITERAL = 21;
+  public const int HEX_LITERAL = 22;
+  public const int OCTAL_LITERAL = 23;
+  public const int FLOATING_POINT_LITERAL = 24;
+  public const int EXPONENT = 25;
+  public const int STRING_LITERAL = 26;
+  public const int ID = 27;
+
+  public const int DEFAULT = 0;
+
+  public readonly string[] tokenImage = {
+    "<EOF>",
+    "\" \"",
+    "\"\\t\"",
+    "\"\\n\"",
+    "\"\\r\"",
+    "\"\\f\"",
+    "<LINE_COMMENT>",
+    "<BLOCK_COMMENT>",
+    "\"NOT\"",
+    "\"AND\"",
+    "\"OR\"",
+    "\"BETWEEN\"",
+    "\"LIKE\"",
+    "\"ESCAPE\"",
+    "\"IN\"",
+    "\"IS\"",
+    "\"TRUE\"",
+    "\"FALSE\"",
+    "\"NULL\"",
+    "\"XPATH\"",
+    "\"XQUERY\"",
+    "<DECIMAL_LITERAL>",
+    "<HEX_LITERAL>",
+    "<OCTAL_LITERAL>",
+    "<FLOATING_POINT_LITERAL>",
+    "<EXPONENT>",
+    "<STRING_LITERAL>",
+    "<ID>",
+    "\"=\"",
+    "\"<>\"",
+    "\">\"",
+    "\">=\"",
+    "\"<\"",
+    "\"<=\"",
+    "\"(\"",
+    "\",\"",
+    "\")\"",
+    "\"+\"",
+    "\"-\"",
+    "\"*\"",
+    "\"/\"",
+    "\"%\"",
+  };
+
+}
diff --git a/src/main/csharp/Selector/SelectorParserTokenManager.cs b/src/main/csharp/Selector/SelectorParserTokenManager.cs
index e198265..99f51e2 100644
--- a/src/main/csharp/Selector/SelectorParserTokenManager.cs
+++ b/src/main/csharp/Selector/SelectorParserTokenManager.cs
@@ -1,1042 +1,1041 @@
-/* Generated By:CSharpCC: Do not edit this line. SelectorParserTokenManager.cs */

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-using System;

-using System.IO;

-using System.Text;

-using System.Collections;

-using Apache.NMS;

-

-public  class SelectorParserTokenManager : SelectorParserConstants {

-  public  System.IO.TextWriter debugStream = Console.Out;

-  public  void SetDebugStream(System.IO.TextWriter ds) { debugStream = ds; }

-private int mccStopAtPos(int pos, int kind)

-{

-   mccmatchedKind = kind;

-   mccmatchedPos = pos;

-   return pos + 1;

-}

-private int mccMoveStringLiteralDfa0_0()

-{

-   switch((int)curChar) {

-      case 9:

-         mccmatchedKind = 2;

-         return mccMoveNfa_0(5, 0);

-      case 10:

-         mccmatchedKind = 3;

-         return mccMoveNfa_0(5, 0);

-      case 12:

-         mccmatchedKind = 5;

-         return mccMoveNfa_0(5, 0);

-      case 13:

-         mccmatchedKind = 4;

-         return mccMoveNfa_0(5, 0);

-      case 32:

-         mccmatchedKind = 1;

-         return mccMoveNfa_0(5, 0);

-      case 37:

-         mccmatchedKind = 41;

-         return mccMoveNfa_0(5, 0);

-      case 40:

-         mccmatchedKind = 34;

-         return mccMoveNfa_0(5, 0);

-      case 41:

-         mccmatchedKind = 36;

-         return mccMoveNfa_0(5, 0);

-      case 42:

-         mccmatchedKind = 39;

-         return mccMoveNfa_0(5, 0);

-      case 43:

-         mccmatchedKind = 37;

-         return mccMoveNfa_0(5, 0);

-      case 44:

-         mccmatchedKind = 35;

-         return mccMoveNfa_0(5, 0);

-      case 45:

-         mccmatchedKind = 38;

-         return mccMoveNfa_0(5, 0);

-      case 47:

-         mccmatchedKind = 40;

-         return mccMoveNfa_0(5, 0);

-      case 60:

-         mccmatchedKind = 32;

-         return mccMoveStringLiteralDfa1_0(9126805504L);

-      case 61:

-         mccmatchedKind = 28;

-         return mccMoveNfa_0(5, 0);

-      case 62:

-         mccmatchedKind = 30;

-         return mccMoveStringLiteralDfa1_0(2147483648L);

-      case 65:

-         return mccMoveStringLiteralDfa1_0(512L);

-      case 66:

-         return mccMoveStringLiteralDfa1_0(2048L);

-      case 69:

-         return mccMoveStringLiteralDfa1_0(8192L);

-      case 70:

-         return mccMoveStringLiteralDfa1_0(131072L);

-      case 73:

-         return mccMoveStringLiteralDfa1_0(49152L);

-      case 76:

-         return mccMoveStringLiteralDfa1_0(4096L);

-      case 78:

-         return mccMoveStringLiteralDfa1_0(262400L);

-      case 79:

-         return mccMoveStringLiteralDfa1_0(1024L);

-      case 84:

-         return mccMoveStringLiteralDfa1_0(65536L);

-      case 88:

-         return mccMoveStringLiteralDfa1_0(1572864L);

-      case 97:

-         return mccMoveStringLiteralDfa1_0(512L);

-      case 98:

-         return mccMoveStringLiteralDfa1_0(2048L);

-      case 101:

-         return mccMoveStringLiteralDfa1_0(8192L);

-      case 102:

-         return mccMoveStringLiteralDfa1_0(131072L);

-      case 105:

-         return mccMoveStringLiteralDfa1_0(49152L);

-      case 108:

-         return mccMoveStringLiteralDfa1_0(4096L);

-      case 110:

-         return mccMoveStringLiteralDfa1_0(262400L);

-      case 111:

-         return mccMoveStringLiteralDfa1_0(1024L);

-      case 116:

-         return mccMoveStringLiteralDfa1_0(65536L);

-      case 120:

-         return mccMoveStringLiteralDfa1_0(1572864L);

-      default :

-         return mccMoveNfa_0(5, 0);

-   }

-}

-private int mccMoveStringLiteralDfa1_0(long active0)

-{

-   try { curChar = input_stream.ReadChar(); }

-   catch(System.IO.IOException) {

-   return mccMoveNfa_0(5, 0);

-   }

-   switch((int)curChar) {

-      case 61:

-         if ((active0 & 2147483648L) != 0L)

-         {

-            mccmatchedKind = 31;

-            mccmatchedPos = 1;

-         }

-         else if ((active0 & 8589934592L) != 0L)

-         {

-            mccmatchedKind = 33;

-            mccmatchedPos = 1;

-         }

-         break;

-      case 62:

-         if ((active0 & 536870912L) != 0L)

-         {

-            mccmatchedKind = 29;

-            mccmatchedPos = 1;

-         }

-         break;

-      case 65:

-         return mccMoveStringLiteralDfa2_0(active0, 131072L);

-      case 69:

-         return mccMoveStringLiteralDfa2_0(active0, 2048L);

-      case 73:

-         return mccMoveStringLiteralDfa2_0(active0, 4096L);

-      case 78:

-         if ((active0 & 16384L) != 0L)

-         {

-            mccmatchedKind = 14;

-            mccmatchedPos = 1;

-         }

-         return mccMoveStringLiteralDfa2_0(active0, 512L);

-      case 79:

-         return mccMoveStringLiteralDfa2_0(active0, 256L);

-      case 80:

-         return mccMoveStringLiteralDfa2_0(active0, 524288L);

-      case 81:

-         return mccMoveStringLiteralDfa2_0(active0, 1048576L);

-      case 82:

-         if ((active0 & 1024L) != 0L)

-         {

-            mccmatchedKind = 10;

-            mccmatchedPos = 1;

-         }

-         return mccMoveStringLiteralDfa2_0(active0, 65536L);

-      case 83:

-         if ((active0 & 32768L) != 0L)

-         {

-            mccmatchedKind = 15;

-            mccmatchedPos = 1;

-         }

-         return mccMoveStringLiteralDfa2_0(active0, 8192L);

-      case 85:

-         return mccMoveStringLiteralDfa2_0(active0, 262144L);

-      case 97:

-         return mccMoveStringLiteralDfa2_0(active0, 131072L);

-      case 101:

-         return mccMoveStringLiteralDfa2_0(active0, 2048L);

-      case 105:

-         return mccMoveStringLiteralDfa2_0(active0, 4096L);

-      case 110:

-         if ((active0 & 16384L) != 0L)

-         {

-            mccmatchedKind = 14;

-            mccmatchedPos = 1;

-         }

-         return mccMoveStringLiteralDfa2_0(active0, 512L);

-      case 111:

-         return mccMoveStringLiteralDfa2_0(active0, 256L);

-      case 112:

-         return mccMoveStringLiteralDfa2_0(active0, 524288L);

-      case 113:

-         return mccMoveStringLiteralDfa2_0(active0, 1048576L);

-      case 114:

-         if ((active0 & 1024L) != 0L)

-         {

-            mccmatchedKind = 10;

-            mccmatchedPos = 1;

-         }

-         return mccMoveStringLiteralDfa2_0(active0, 65536L);

-      case 115:

-         if ((active0 & 32768L) != 0L)

-         {

-            mccmatchedKind = 15;

-            mccmatchedPos = 1;

-         }

-         return mccMoveStringLiteralDfa2_0(active0, 8192L);

-      case 117:

-         return mccMoveStringLiteralDfa2_0(active0, 262144L);

-      default :

-         break;

-   }

-   return mccMoveNfa_0(5, 1);

-}

-private int mccMoveStringLiteralDfa2_0(long old0, long active0)

-{

-   if (((active0 &= old0)) == 0L)

-      return mccMoveNfa_0(5, 1);

-   try { curChar = input_stream.ReadChar(); }

-   catch(System.IO.IOException) {

-   return mccMoveNfa_0(5, 1);

-   }

-   switch((int)curChar) {

-      case 65:

-         return mccMoveStringLiteralDfa3_0(active0, 524288L);

-      case 67:

-         return mccMoveStringLiteralDfa3_0(active0, 8192L);

-      case 68:

-         if ((active0 & 512L) != 0L)

-         {

-            mccmatchedKind = 9;

-            mccmatchedPos = 2;

-         }

-         break;

-      case 75:

-         return mccMoveStringLiteralDfa3_0(active0, 4096L);

-      case 76:

-         return mccMoveStringLiteralDfa3_0(active0, 393216L);

-      case 84:

-         if ((active0 & 256L) != 0L)

-         {

-            mccmatchedKind = 8;

-            mccmatchedPos = 2;

-         }

-         return mccMoveStringLiteralDfa3_0(active0, 2048L);

-      case 85:

-         return mccMoveStringLiteralDfa3_0(active0, 1114112L);

-      case 97:

-         return mccMoveStringLiteralDfa3_0(active0, 524288L);

-      case 99:

-         return mccMoveStringLiteralDfa3_0(active0, 8192L);

-      case 100:

-         if ((active0 & 512L) != 0L)

-         {

-            mccmatchedKind = 9;

-            mccmatchedPos = 2;

-         }

-         break;

-      case 107:

-         return mccMoveStringLiteralDfa3_0(active0, 4096L);

-      case 108:

-         return mccMoveStringLiteralDfa3_0(active0, 393216L);

-      case 116:

-         if ((active0 & 256L) != 0L)

-         {

-            mccmatchedKind = 8;

-            mccmatchedPos = 2;

-         }

-         return mccMoveStringLiteralDfa3_0(active0, 2048L);

-      case 117:

-         return mccMoveStringLiteralDfa3_0(active0, 1114112L);

-      default :

-         break;

-   }

-   return mccMoveNfa_0(5, 2);

-}

-private int mccMoveStringLiteralDfa3_0(long old0, long active0)

-{

-   if (((active0 &= old0)) == 0L)

-      return mccMoveNfa_0(5, 2);

-   try { curChar = input_stream.ReadChar(); }

-   catch(System.IO.IOException) {

-   return mccMoveNfa_0(5, 2);

-   }

-   switch((int)curChar) {

-      case 65:

-         return mccMoveStringLiteralDfa4_0(active0, 8192L);

-      case 69:

-         if ((active0 & 4096L) != 0L)

-         {

-            mccmatchedKind = 12;

-            mccmatchedPos = 3;

-         }

-         else if ((active0 & 65536L) != 0L)

-         {

-            mccmatchedKind = 16;

-            mccmatchedPos = 3;

-         }

-         return mccMoveStringLiteralDfa4_0(active0, 1048576L);

-      case 76:

-         if ((active0 & 262144L) != 0L)

-         {

-            mccmatchedKind = 18;

-            mccmatchedPos = 3;

-         }

-         break;

-      case 83:

-         return mccMoveStringLiteralDfa4_0(active0, 131072L);

-      case 84:

-         return mccMoveStringLiteralDfa4_0(active0, 524288L);

-      case 87:

-         return mccMoveStringLiteralDfa4_0(active0, 2048L);

-      case 97:

-         return mccMoveStringLiteralDfa4_0(active0, 8192L);

-      case 101:

-         if ((active0 & 4096L) != 0L)

-         {

-            mccmatchedKind = 12;

-            mccmatchedPos = 3;

-         }

-         else if ((active0 & 65536L) != 0L)

-         {

-            mccmatchedKind = 16;

-            mccmatchedPos = 3;

-         }

-         return mccMoveStringLiteralDfa4_0(active0, 1048576L);

-      case 108:

-         if ((active0 & 262144L) != 0L)

-         {

-            mccmatchedKind = 18;

-            mccmatchedPos = 3;

-         }

-         break;

-      case 115:

-         return mccMoveStringLiteralDfa4_0(active0, 131072L);

-      case 116:

-         return mccMoveStringLiteralDfa4_0(active0, 524288L);

-      case 119:

-         return mccMoveStringLiteralDfa4_0(active0, 2048L);

-      default :

-         break;

-   }

-   return mccMoveNfa_0(5, 3);

-}

-private int mccMoveStringLiteralDfa4_0(long old0, long active0)

-{

-   if (((active0 &= old0)) == 0L)

-      return mccMoveNfa_0(5, 3);

-   try { curChar = input_stream.ReadChar(); }

-   catch(System.IO.IOException) {

-   return mccMoveNfa_0(5, 3);

-   }

-   switch((int)curChar) {

-      case 69:

-         if ((active0 & 131072L) != 0L)

-         {

-            mccmatchedKind = 17;

-            mccmatchedPos = 4;

-         }

-         return mccMoveStringLiteralDfa5_0(active0, 2048L);

-      case 72:

-         if ((active0 & 524288L) != 0L)

-         {

-            mccmatchedKind = 19;

-            mccmatchedPos = 4;

-         }

-         break;

-      case 80:

-         return mccMoveStringLiteralDfa5_0(active0, 8192L);

-      case 82:

-         return mccMoveStringLiteralDfa5_0(active0, 1048576L);

-      case 101:

-         if ((active0 & 131072L) != 0L)

-         {

-            mccmatchedKind = 17;

-            mccmatchedPos = 4;

-         }

-         return mccMoveStringLiteralDfa5_0(active0, 2048L);

-      case 104:

-         if ((active0 & 524288L) != 0L)

-         {

-            mccmatchedKind = 19;

-            mccmatchedPos = 4;

-         }

-         break;

-      case 112:

-         return mccMoveStringLiteralDfa5_0(active0, 8192L);

-      case 114:

-         return mccMoveStringLiteralDfa5_0(active0, 1048576L);

-      default :

-         break;

-   }

-   return mccMoveNfa_0(5, 4);

-}

-private int mccMoveStringLiteralDfa5_0(long old0, long active0)

-{

-   if (((active0 &= old0)) == 0L)

-      return mccMoveNfa_0(5, 4);

-   try { curChar = input_stream.ReadChar(); }

-   catch(System.IO.IOException) {

-   return mccMoveNfa_0(5, 4);

-   }

-   switch((int)curChar) {

-      case 69:

-         if ((active0 & 8192L) != 0L)

-         {

-            mccmatchedKind = 13;

-            mccmatchedPos = 5;

-         }

-         return mccMoveStringLiteralDfa6_0(active0, 2048L);

-      case 89:

-         if ((active0 & 1048576L) != 0L)

-         {

-            mccmatchedKind = 20;

-            mccmatchedPos = 5;

-         }

-         break;

-      case 101:

-         if ((active0 & 8192L) != 0L)

-         {

-            mccmatchedKind = 13;

-            mccmatchedPos = 5;

-         }

-         return mccMoveStringLiteralDfa6_0(active0, 2048L);

-      case 121:

-         if ((active0 & 1048576L) != 0L)

-         {

-            mccmatchedKind = 20;

-            mccmatchedPos = 5;

-         }

-         break;

-      default :

-         break;

-   }

-   return mccMoveNfa_0(5, 5);

-}

-private int mccMoveStringLiteralDfa6_0(long old0, long active0)

-{

-   if (((active0 &= old0)) == 0L)

-      return mccMoveNfa_0(5, 5);

-   try { curChar = input_stream.ReadChar(); }

-   catch(System.IO.IOException) {

-   return mccMoveNfa_0(5, 5);

-   }

-   switch((int)curChar) {

-      case 78:

-         if ((active0 & 2048L) != 0L)

-         {

-            mccmatchedKind = 11;

-            mccmatchedPos = 6;

-         }

-         break;

-      case 110:

-         if ((active0 & 2048L) != 0L)

-         {

-            mccmatchedKind = 11;

-            mccmatchedPos = 6;

-         }

-         break;

-      default :

-         break;

-   }

-   return mccMoveNfa_0(5, 6);

-}

-private void mccCheckNAdd(int state)

-{

-   if (mccrounds[state] != mccround)

-   {

-      mccstateSet[mccnewStateCnt++] = state;

-      mccrounds[state] = mccround;

-   }

-}

-private void mccAddStates(int start, int end)

-{

-   do {

-      mccstateSet[mccnewStateCnt++] = mccnextStates[start];

-   } while (start++ != end);

-}

-private void mccCheckNAddTwoStates(int state1, int state2)

-{

-   mccCheckNAdd(state1);

-   mccCheckNAdd(state2);

-}

-private void mccCheckNAddStates(int start, int end)

-{

-   do {

-      mccCheckNAdd(mccnextStates[start]);

-   } while (start++ != end);

-}

-private void mccCheckNAddStates(int start)

-{

-   mccCheckNAdd(mccnextStates[start]);

-   mccCheckNAdd(mccnextStates[start + 1]);

-}

+/* Generated By:CSharpCC: Do not edit this line. SelectorParserTokenManager.cs */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.IO;
+using System.Text;
+using System.Collections;
+using Apache.NMS;
+
+public  class SelectorParserTokenManager : SelectorParserConstants {
+  public  System.IO.TextWriter debugStream = Console.Out;
+  public  void SetDebugStream(System.IO.TextWriter ds) { debugStream = ds; }
+private int mccStopAtPos(int pos, int kind)
+{
+   mccmatchedKind = kind;
+   mccmatchedPos = pos;
+   return pos + 1;
+}
+private int mccMoveStringLiteralDfa0_0()
+{
+   switch((int)curChar) {
+      case 9:
+         mccmatchedKind = 2;
+         return mccMoveNfa_0(5, 0);
+      case 10:
+         mccmatchedKind = 3;
+         return mccMoveNfa_0(5, 0);
+      case 12:
+         mccmatchedKind = 5;
+         return mccMoveNfa_0(5, 0);
+      case 13:
+         mccmatchedKind = 4;
+         return mccMoveNfa_0(5, 0);
+      case 32:
+         mccmatchedKind = 1;
+         return mccMoveNfa_0(5, 0);
+      case 37:
+         mccmatchedKind = 41;
+         return mccMoveNfa_0(5, 0);
+      case 40:
+         mccmatchedKind = 34;
+         return mccMoveNfa_0(5, 0);
+      case 41:
+         mccmatchedKind = 36;
+         return mccMoveNfa_0(5, 0);
+      case 42:
+         mccmatchedKind = 39;
+         return mccMoveNfa_0(5, 0);
+      case 43:
+         mccmatchedKind = 37;
+         return mccMoveNfa_0(5, 0);
+      case 44:
+         mccmatchedKind = 35;
+         return mccMoveNfa_0(5, 0);
+      case 45:
+         mccmatchedKind = 38;
+         return mccMoveNfa_0(5, 0);
+      case 47:
+         mccmatchedKind = 40;
+         return mccMoveNfa_0(5, 0);
+      case 60:
+         mccmatchedKind = 32;
+         return mccMoveStringLiteralDfa1_0(9126805504L);
+      case 61:
+         mccmatchedKind = 28;
+         return mccMoveNfa_0(5, 0);
+      case 62:
+         mccmatchedKind = 30;
+         return mccMoveStringLiteralDfa1_0(2147483648L);
+      case 65:
+         return mccMoveStringLiteralDfa1_0(512L);
+      case 66:
+         return mccMoveStringLiteralDfa1_0(2048L);
+      case 69:
+         return mccMoveStringLiteralDfa1_0(8192L);
+      case 70:
+         return mccMoveStringLiteralDfa1_0(131072L);
+      case 73:
+         return mccMoveStringLiteralDfa1_0(49152L);
+      case 76:
+         return mccMoveStringLiteralDfa1_0(4096L);
+      case 78:
+         return mccMoveStringLiteralDfa1_0(262400L);
+      case 79:
+         return mccMoveStringLiteralDfa1_0(1024L);
+      case 84:
+         return mccMoveStringLiteralDfa1_0(65536L);
+      case 88:
+         return mccMoveStringLiteralDfa1_0(1572864L);
+      case 97:
+         return mccMoveStringLiteralDfa1_0(512L);
+      case 98:
+         return mccMoveStringLiteralDfa1_0(2048L);
+      case 101:
+         return mccMoveStringLiteralDfa1_0(8192L);
+      case 102:
+         return mccMoveStringLiteralDfa1_0(131072L);
+      case 105:
+         return mccMoveStringLiteralDfa1_0(49152L);
+      case 108:
+         return mccMoveStringLiteralDfa1_0(4096L);
+      case 110:
+         return mccMoveStringLiteralDfa1_0(262400L);
+      case 111:
+         return mccMoveStringLiteralDfa1_0(1024L);
+      case 116:
+         return mccMoveStringLiteralDfa1_0(65536L);
+      case 120:
+         return mccMoveStringLiteralDfa1_0(1572864L);
+      default :
+         return mccMoveNfa_0(5, 0);
+   }
+}
+private int mccMoveStringLiteralDfa1_0(long active0)
+{
+   try { curChar = input_stream.ReadChar(); }
+   catch(System.IO.IOException) {
+   return mccMoveNfa_0(5, 0);
+   }
+   switch((int)curChar) {
+      case 61:
+         if ((active0 & 2147483648L) != 0L)
+         {
+            mccmatchedKind = 31;
+            mccmatchedPos = 1;
+         }
+         else if ((active0 & 8589934592L) != 0L)
+         {
+            mccmatchedKind = 33;
+            mccmatchedPos = 1;
+         }
+         break;
+      case 62:
+         if ((active0 & 536870912L) != 0L)
+         {
+            mccmatchedKind = 29;
+            mccmatchedPos = 1;
+         }
+         break;
+      case 65:
+         return mccMoveStringLiteralDfa2_0(active0, 131072L);
+      case 69:
+         return mccMoveStringLiteralDfa2_0(active0, 2048L);
+      case 73:
+         return mccMoveStringLiteralDfa2_0(active0, 4096L);
+      case 78:
+         if ((active0 & 16384L) != 0L)
+         {
+            mccmatchedKind = 14;
+            mccmatchedPos = 1;
+         }
+         return mccMoveStringLiteralDfa2_0(active0, 512L);
+      case 79:
+         return mccMoveStringLiteralDfa2_0(active0, 256L);
+      case 80:
+         return mccMoveStringLiteralDfa2_0(active0, 524288L);
+      case 81:
+         return mccMoveStringLiteralDfa2_0(active0, 1048576L);
+      case 82:
+         if ((active0 & 1024L) != 0L)
+         {
+            mccmatchedKind = 10;
+            mccmatchedPos = 1;
+         }
+         return mccMoveStringLiteralDfa2_0(active0, 65536L);
+      case 83:
+         if ((active0 & 32768L) != 0L)
+         {
+            mccmatchedKind = 15;
+            mccmatchedPos = 1;
+         }
+         return mccMoveStringLiteralDfa2_0(active0, 8192L);
+      case 85:
+         return mccMoveStringLiteralDfa2_0(active0, 262144L);
+      case 97:
+         return mccMoveStringLiteralDfa2_0(active0, 131072L);
+      case 101:
+         return mccMoveStringLiteralDfa2_0(active0, 2048L);
+      case 105:
+         return mccMoveStringLiteralDfa2_0(active0, 4096L);
+      case 110:
+         if ((active0 & 16384L) != 0L)
+         {
+            mccmatchedKind = 14;
+            mccmatchedPos = 1;
+         }
+         return mccMoveStringLiteralDfa2_0(active0, 512L);
+      case 111:
+         return mccMoveStringLiteralDfa2_0(active0, 256L);
+      case 112:
+         return mccMoveStringLiteralDfa2_0(active0, 524288L);
+      case 113:
+         return mccMoveStringLiteralDfa2_0(active0, 1048576L);
+      case 114:
+         if ((active0 & 1024L) != 0L)
+         {
+            mccmatchedKind = 10;
+            mccmatchedPos = 1;
+         }
+         return mccMoveStringLiteralDfa2_0(active0, 65536L);
+      case 115:
+         if ((active0 & 32768L) != 0L)
+         {
+            mccmatchedKind = 15;
+            mccmatchedPos = 1;
+         }
+         return mccMoveStringLiteralDfa2_0(active0, 8192L);
+      case 117:
+         return mccMoveStringLiteralDfa2_0(active0, 262144L);
+      default :
+         break;
+   }
+   return mccMoveNfa_0(5, 1);
+}
+private int mccMoveStringLiteralDfa2_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return mccMoveNfa_0(5, 1);
+   try { curChar = input_stream.ReadChar(); }
+   catch(System.IO.IOException) {
+   return mccMoveNfa_0(5, 1);
+   }
+   switch((int)curChar) {
+      case 65:
+         return mccMoveStringLiteralDfa3_0(active0, 524288L);
+      case 67:
+         return mccMoveStringLiteralDfa3_0(active0, 8192L);
+      case 68:
+         if ((active0 & 512L) != 0L)
+         {
+            mccmatchedKind = 9;
+            mccmatchedPos = 2;
+         }
+         break;
+      case 75:
+         return mccMoveStringLiteralDfa3_0(active0, 4096L);
+      case 76:
+         return mccMoveStringLiteralDfa3_0(active0, 393216L);
+      case 84:
+         if ((active0 & 256L) != 0L)
+         {
+            mccmatchedKind = 8;
+            mccmatchedPos = 2;
+         }
+         return mccMoveStringLiteralDfa3_0(active0, 2048L);
+      case 85:
+         return mccMoveStringLiteralDfa3_0(active0, 1114112L);
+      case 97:
+         return mccMoveStringLiteralDfa3_0(active0, 524288L);
+      case 99:
+         return mccMoveStringLiteralDfa3_0(active0, 8192L);
+      case 100:
+         if ((active0 & 512L) != 0L)
+         {
+            mccmatchedKind = 9;
+            mccmatchedPos = 2;
+         }
+         break;
+      case 107:
+         return mccMoveStringLiteralDfa3_0(active0, 4096L);
+      case 108:
+         return mccMoveStringLiteralDfa3_0(active0, 393216L);
+      case 116:
+         if ((active0 & 256L) != 0L)
+         {
+            mccmatchedKind = 8;
+            mccmatchedPos = 2;
+         }
+         return mccMoveStringLiteralDfa3_0(active0, 2048L);
+      case 117:
+         return mccMoveStringLiteralDfa3_0(active0, 1114112L);
+      default :
+         break;
+   }
+   return mccMoveNfa_0(5, 2);
+}
+private int mccMoveStringLiteralDfa3_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return mccMoveNfa_0(5, 2);
+   try { curChar = input_stream.ReadChar(); }
+   catch(System.IO.IOException) {
+   return mccMoveNfa_0(5, 2);
+   }
+   switch((int)curChar) {
+      case 65:
+         return mccMoveStringLiteralDfa4_0(active0, 8192L);
+      case 69:
+         if ((active0 & 4096L) != 0L)
+         {
+            mccmatchedKind = 12;
+            mccmatchedPos = 3;
+         }
+         else if ((active0 & 65536L) != 0L)
+         {
+            mccmatchedKind = 16;
+            mccmatchedPos = 3;
+         }
+         return mccMoveStringLiteralDfa4_0(active0, 1048576L);
+      case 76:
+         if ((active0 & 262144L) != 0L)
+         {
+            mccmatchedKind = 18;
+            mccmatchedPos = 3;
+         }
+         break;
+      case 83:
+         return mccMoveStringLiteralDfa4_0(active0, 131072L);
+      case 84:
+         return mccMoveStringLiteralDfa4_0(active0, 524288L);
+      case 87:
+         return mccMoveStringLiteralDfa4_0(active0, 2048L);
+      case 97:
+         return mccMoveStringLiteralDfa4_0(active0, 8192L);
+      case 101:
+         if ((active0 & 4096L) != 0L)
+         {
+            mccmatchedKind = 12;
+            mccmatchedPos = 3;
+         }
+         else if ((active0 & 65536L) != 0L)
+         {
+            mccmatchedKind = 16;
+            mccmatchedPos = 3;
+         }
+         return mccMoveStringLiteralDfa4_0(active0, 1048576L);
+      case 108:
+         if ((active0 & 262144L) != 0L)
+         {
+            mccmatchedKind = 18;
+            mccmatchedPos = 3;
+         }
+         break;
+      case 115:
+         return mccMoveStringLiteralDfa4_0(active0, 131072L);
+      case 116:
+         return mccMoveStringLiteralDfa4_0(active0, 524288L);
+      case 119:
+         return mccMoveStringLiteralDfa4_0(active0, 2048L);
+      default :
+         break;
+   }
+   return mccMoveNfa_0(5, 3);
+}
+private int mccMoveStringLiteralDfa4_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return mccMoveNfa_0(5, 3);
+   try { curChar = input_stream.ReadChar(); }
+   catch(System.IO.IOException) {
+   return mccMoveNfa_0(5, 3);
+   }
+   switch((int)curChar) {
+      case 69:
+         if ((active0 & 131072L) != 0L)
+         {
+            mccmatchedKind = 17;
+            mccmatchedPos = 4;
+         }
+         return mccMoveStringLiteralDfa5_0(active0, 2048L);
+      case 72:
+         if ((active0 & 524288L) != 0L)
+         {
+            mccmatchedKind = 19;
+            mccmatchedPos = 4;
+         }
+         break;
+      case 80:
+         return mccMoveStringLiteralDfa5_0(active0, 8192L);
+      case 82:
+         return mccMoveStringLiteralDfa5_0(active0, 1048576L);
+      case 101:
+         if ((active0 & 131072L) != 0L)
+         {
+            mccmatchedKind = 17;
+            mccmatchedPos = 4;
+         }
+         return mccMoveStringLiteralDfa5_0(active0, 2048L);
+      case 104:
+         if ((active0 & 524288L) != 0L)
+         {
+            mccmatchedKind = 19;
+            mccmatchedPos = 4;
+         }
+         break;
+      case 112:
+         return mccMoveStringLiteralDfa5_0(active0, 8192L);
+      case 114:
+         return mccMoveStringLiteralDfa5_0(active0, 1048576L);
+      default :
+         break;
+   }
+   return mccMoveNfa_0(5, 4);
+}
+private int mccMoveStringLiteralDfa5_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return mccMoveNfa_0(5, 4);
+   try { curChar = input_stream.ReadChar(); }
+   catch(System.IO.IOException) {
+   return mccMoveNfa_0(5, 4);
+   }
+   switch((int)curChar) {
+      case 69:
+         if ((active0 & 8192L) != 0L)
+         {
+            mccmatchedKind = 13;
+            mccmatchedPos = 5;
+         }
+         return mccMoveStringLiteralDfa6_0(active0, 2048L);
+      case 89:
+         if ((active0 & 1048576L) != 0L)
+         {
+            mccmatchedKind = 20;
+            mccmatchedPos = 5;
+         }
+         break;
+      case 101:
+         if ((active0 & 8192L) != 0L)
+         {
+            mccmatchedKind = 13;
+            mccmatchedPos = 5;
+         }
+         return mccMoveStringLiteralDfa6_0(active0, 2048L);
+      case 121:
+         if ((active0 & 1048576L) != 0L)
+         {
+            mccmatchedKind = 20;
+            mccmatchedPos = 5;
+         }
+         break;
+      default :
+         break;
+   }
+   return mccMoveNfa_0(5, 5);
+}
+private int mccMoveStringLiteralDfa6_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return mccMoveNfa_0(5, 5);
+   try { curChar = input_stream.ReadChar(); }
+   catch(System.IO.IOException) {
+   return mccMoveNfa_0(5, 5);
+   }
+   switch((int)curChar) {
+      case 78:
+         if ((active0 & 2048L) != 0L)
+         {
+            mccmatchedKind = 11;
+            mccmatchedPos = 6;
+         }
+         break;
+      case 110:
+         if ((active0 & 2048L) != 0L)
+         {
+            mccmatchedKind = 11;
+            mccmatchedPos = 6;
+         }
+         break;
+      default :
+         break;
+   }
+   return mccMoveNfa_0(5, 6);
+}
+private void mccCheckNAdd(int state)
+{
+   if (mccrounds[state] != mccround)
+   {
+      mccstateSet[mccnewStateCnt++] = state;
+      mccrounds[state] = mccround;
+   }
+}
+private void mccAddStates(int start, int end)
+{
+   do {
+      mccstateSet[mccnewStateCnt++] = mccnextStates[start];
+   } while (start++ != end);
+}
+private void mccCheckNAddTwoStates(int state1, int state2)
+{
+   mccCheckNAdd(state1);
+   mccCheckNAdd(state2);
+}
+private void mccCheckNAddStates(int start, int end)
+{
+   do {
+      mccCheckNAdd(mccnextStates[start]);
+   } while (start++ != end);
+}
+private void mccCheckNAddStates(int start)
+{
+   mccCheckNAdd(mccnextStates[start]);
+   mccCheckNAdd(mccnextStates[start + 1]);
+}
 static readonly long[] mccbitVec0 = {
    -2, -1L, -1L, -1L
-};

+};
 static readonly long[] mccbitVec1 = {
    -1L, -1L, -1L, -1L
-};

+};
 static readonly long[] mccbitVec2 = {
    0L, 0L, -1L, -1L
-};

-private int mccMoveNfa_0(int startState, int curPos)

-{

-   int strKind = mccmatchedKind;

-   int strPos = mccmatchedPos;

-   int seenUpto = curPos + 1;

-   input_stream.Backup(seenUpto);

-   try { curChar = input_stream.ReadChar(); }

-   catch(System.IO.IOException) { throw new Exception("Internal Error"); }

-   curPos = 0;

-   //int[] nextStates;

-   int startsAt = 0;

-   mccnewStateCnt = 43;

-   int i = 1;

-   mccstateSet[0] = startState;

-   int /*j,*/ kind = Int32.MaxValue;

-   for (;;)

-   {

-      if (++mccround == Int32.MaxValue)

-         ReInitRounds();

-      if (curChar < 64)

-      {

-         long l = 1L << curChar;

-         do

-         {

-            switch(mccstateSet[--i])

-            {

-               case 5:

-                  if ((287948901175001088 & l) != 0L)

-                     mccCheckNAddStates(0, 3);

-                  else if (curChar == 36)

-                  {

-                     if (kind > 27)

-                        kind = 27;

-                     mccCheckNAdd(27);

-                  }

-                  else if (curChar == 39)

-                     mccCheckNAddStates(4, 6);

-                  else if (curChar == 46)

-                     mccCheckNAdd(17);

-                  else if (curChar == 47)

-                     mccstateSet[mccnewStateCnt++] = 6;

-                  else if (curChar == 45)

-                     mccstateSet[mccnewStateCnt++] = 0;

-                  if ((287667426198290432 & l) != 0L)

-                  {

-                     if (kind > 21)

-                        kind = 21;

-                     mccCheckNAddTwoStates(14, 15);

-                  }

-                  else if (curChar == 48)

-                  {

-                     if (kind > 23)

-                        kind = 23;

-                     mccCheckNAddTwoStates(40, 42);

-                  }

-                  break;

-               case 0:

-                  if (curChar == 45)

-                     mccCheckNAddStates(7, 9);

-                  break;

-               case 1:

-                  if ((-9217 & l) != 0L)

-                     mccCheckNAddStates(7, 9);

-                  break;

-               case 2:

-                  if ((9216 & l) != 0L && kind > 6)

-                     kind = 6;

-                  break;

-               case 3:

-                  if (curChar == 10 && kind > 6)

-                     kind = 6;

-                  break;

-               case 4:

-                  if (curChar == 13)

-                     mccstateSet[mccnewStateCnt++] = 3;

-                  break;

-               case 6:

-                  if (curChar == 42)

-                     mccCheckNAddTwoStates(7, 8);

-                  break;

-               case 7:

-                  if ((-4398046511105 & l) != 0L)

-                     mccCheckNAddTwoStates(7, 8);

-                  break;

-               case 8:

-                  if (curChar == 42)

-                     mccCheckNAddStates(10, 12);

-                  break;

-               case 9:

-                  if ((-145135534866433 & l) != 0L)

-                     mccCheckNAddTwoStates(10, 8);

-                  break;

-               case 10:

-                  if ((-4398046511105 & l) != 0L)

-                     mccCheckNAddTwoStates(10, 8);

-                  break;

-               case 11:

-                  if (curChar == 47 && kind > 7)

-                     kind = 7;

-                  break;

-               case 12:

-                  if (curChar == 47)

-                     mccstateSet[mccnewStateCnt++] = 6;

-                  break;

-               case 13:

-                  if ((287667426198290432 & l) == 0L)

-                     break;

-                  if (kind > 21)

-                     kind = 21;

-                  mccCheckNAddTwoStates(14, 15);

-                  break;

-               case 14:

-                  if ((287948901175001088 & l) == 0L)

-                     break;

-                  if (kind > 21)

-                     kind = 21;

-                  mccCheckNAddTwoStates(14, 15);

-                  break;

-               case 16:

-                  if (curChar == 46)

-                     mccCheckNAdd(17);

-                  break;

-               case 17:

-                  if ((287948901175001088 & l) == 0L)

-                     break;

-                  if (kind > 24)

-                     kind = 24;

-                  mccCheckNAddTwoStates(17, 18);

-                  break;

-               case 19:

-                  if ((43980465111040 & l) != 0L)

-                     mccCheckNAdd(20);

-                  break;

-               case 20:

-                  if ((287948901175001088 & l) == 0L)

-                     break;

-                  if (kind > 24)

-                     kind = 24;

-                  mccCheckNAdd(20);

-                  break;

-               case 21:

-               case 22:

-                  if (curChar == 39)

-                     mccCheckNAddStates(4, 6);

-                  break;

-               case 23:

-                  if (curChar == 39)

-                     mccstateSet[mccnewStateCnt++] = 22;

-                  break;

-               case 24:

-                  if ((-549755813889 & l) != 0L)

-                     mccCheckNAddStates(4, 6);

-                  break;

-               case 25:

-                  if (curChar == 39 && kind > 26)

-                     kind = 26;

-                  break;

-               case 26:

-                  if (curChar != 36)

-                     break;

-                  if (kind > 27)

-                     kind = 27;

-                  mccCheckNAdd(27);

-                  break;

-               case 27:

-                  if ((287948969894477824 & l) == 0L)

-                     break;

-                  if (kind > 27)

-                     kind = 27;

-                  mccCheckNAdd(27);

-                  break;

-               case 28:

-                  if ((287948901175001088 & l) != 0L)

-                     mccCheckNAddStates(0, 3);

-                  break;

-               case 29:

-                  if ((287948901175001088 & l) != 0L)

-                     mccCheckNAddTwoStates(29, 30);

-                  break;

-               case 30:

-                  if (curChar != 46)

-                     break;

-                  if (kind > 24)

-                     kind = 24;

-                  mccCheckNAddTwoStates(31, 32);

-                  break;

-               case 31:

-                  if ((287948901175001088 & l) == 0L)

-                     break;

-                  if (kind > 24)

-                     kind = 24;

-                  mccCheckNAddTwoStates(31, 32);

-                  break;

-               case 33:

-                  if ((43980465111040 & l) != 0L)

-                     mccCheckNAdd(34);

-                  break;

-               case 34:

-                  if ((287948901175001088 & l) == 0L)

-                     break;

-                  if (kind > 24)

-                     kind = 24;

-                  mccCheckNAdd(34);

-                  break;

-               case 35:

-                  if ((287948901175001088 & l) != 0L)

-                     mccCheckNAddTwoStates(35, 36);

-                  break;

-               case 37:

-                  if ((43980465111040 & l) != 0L)

-                     mccCheckNAdd(38);

-                  break;

-               case 38:

-                  if ((287948901175001088 & l) == 0L)

-                     break;

-                  if (kind > 24)

-                     kind = 24;

-                  mccCheckNAdd(38);

-                  break;

-               case 39:

-                  if (curChar != 48)

-                     break;

-                  if (kind > 23)

-                     kind = 23;

-                  mccCheckNAddTwoStates(40, 42);

-                  break;

-               case 41:

-                  if ((287948901175001088 & l) == 0L)

-                     break;

-                  if (kind > 22)

-                     kind = 22;

-                  mccstateSet[mccnewStateCnt++] = 41;

-                  break;

-               case 42:

-                  if ((71776119061217280 & l) == 0L)

-                     break;

-                  if (kind > 23)

-                     kind = 23;

-                  mccCheckNAdd(42);

-                  break;

-               default : break;

-            }

-         } while(i != startsAt);

-      }

-      else if (curChar < 128)

-      {

-         long l = 1L << (curChar & 63);

-         do

-         {

-            switch(mccstateSet[--i])

-            {

-               case 5:

-               case 27:

-                  if ((576460745995190270 & l) == 0L)

-                     break;

-                  if (kind > 27)

-                     kind = 27;

-                  mccCheckNAdd(27);

-                  break;

-               case 1:

-                  mccAddStates(7, 9);

-                  break;

-               case 7:

-                  mccCheckNAddTwoStates(7, 8);

-                  break;

-               case 9:

-               case 10:

-                  mccCheckNAddTwoStates(10, 8);

-                  break;

-               case 15:

-                  if ((17592186048512 & l) != 0L && kind > 21)

-                     kind = 21;

-                  break;

-               case 18:

-                  if ((137438953504 & l) != 0L)

-                     mccAddStates(13, 14);

-                  break;

-               case 24:

-                  mccAddStates(4, 6);

-                  break;

-               case 32:

-                  if ((137438953504 & l) != 0L)

-                     mccAddStates(15, 16);

-                  break;

-               case 36:

-                  if ((137438953504 & l) != 0L)

-                     mccAddStates(17, 18);

-                  break;

-               case 40:

-                  if ((72057594054705152 & l) != 0L)

-                     mccCheckNAdd(41);

-                  break;

-               case 41:

-                  if ((541165879422 & l) == 0L)

-                     break;

-                  if (kind > 22)

-                     kind = 22;

-                  mccCheckNAdd(41);

-                  break;

-               default : break;

-            }

-         } while(i != startsAt);

-      }

-      else

-      {

-         int hiByte = (curChar >> 8);

-         int i1 = hiByte >> 6;

-         long l1 = 1L << (hiByte & 63);

-         int i2 = (curChar & 0xff) >> 6;

-         long l2 = 1L << (curChar & 63);

-         do

-         {

-            switch(mccstateSet[--i])

-            {

-               case 1:

-                  if (mccCanMove_0(hiByte, i1, i2, l1, l2))

-                     mccAddStates(7, 9);

-                  break;

-               case 7:

-                  if (mccCanMove_0(hiByte, i1, i2, l1, l2))

-                     mccCheckNAddTwoStates(7, 8);

-                  break;

-               case 9:

-               case 10:

-                  if (mccCanMove_0(hiByte, i1, i2, l1, l2))

-                     mccCheckNAddTwoStates(10, 8);

-                  break;

-               case 24:

-                  if (mccCanMove_0(hiByte, i1, i2, l1, l2))

-                     mccAddStates(4, 6);

-                  break;

-               default : break;

-            }

-         } while(i != startsAt);

-      }

-      if (kind != Int32.MaxValue)

-      {

-         mccmatchedKind = kind;

-         mccmatchedPos = curPos;

-         kind = Int32.MaxValue;

-      }

-      ++curPos;

-      if ((i = mccnewStateCnt) == (startsAt = 43 - (mccnewStateCnt = startsAt)))

-         break;

-      try { curChar = input_stream.ReadChar(); }

-      catch(System.IO.IOException) { break; }

-   }

-   if (mccmatchedPos > strPos)

-      return curPos;

-

-   int toRet = Math.Max(curPos, seenUpto);

-

-   if (curPos < toRet)

-      for (i = toRet - Math.Min(curPos, seenUpto); i-- > 0; )

-         try { curChar = input_stream.ReadChar(); }

-         catch(System.IO.IOException) { throw new Exception("Internal Error : Please send a bug report."); }

-

-   if (mccmatchedPos < strPos)

-   {

-      mccmatchedKind = strKind;

-      mccmatchedPos = strPos;

-   }

-   else if (mccmatchedPos == strPos && mccmatchedKind > strKind)

-      mccmatchedKind = strKind;

-

-   return toRet;

-}

+};
+private int mccMoveNfa_0(int startState, int curPos)
+{
+   int strKind = mccmatchedKind;
+   int strPos = mccmatchedPos;
+   int seenUpto = curPos + 1;
+   input_stream.Backup(seenUpto);
+   try { curChar = input_stream.ReadChar(); }
+   catch(System.IO.IOException) { throw new Exception("Internal Error"); }
+   curPos = 0;
+   //int[] nextStates;
+   int startsAt = 0;
+   mccnewStateCnt = 43;
+   int i = 1;
+   mccstateSet[0] = startState;
+   int /*j,*/ kind = Int32.MaxValue;
+   for (;;)
+   {
+      if (++mccround == Int32.MaxValue)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(mccstateSet[--i])
+            {
+               case 5:
+                  if ((287948901175001088 & l) != 0L)
+                     mccCheckNAddStates(0, 3);
+                  else if (curChar == 36)
+                  {
+                     if (kind > 27)
+                        kind = 27;
+                     mccCheckNAdd(27);
+                  }
+                  else if (curChar == 39)
+                     mccCheckNAddStates(4, 6);
+                  else if (curChar == 46)
+                     mccCheckNAdd(17);
+                  else if (curChar == 47)
+                     mccstateSet[mccnewStateCnt++] = 6;
+                  else if (curChar == 45)
+                     mccstateSet[mccnewStateCnt++] = 0;
+                  if ((287667426198290432 & l) != 0L)
+                  {
+                     if (kind > 21)
+                        kind = 21;
+                     mccCheckNAddTwoStates(14, 15);
+                  }
+                  else if (curChar == 48)
+                  {
+                     if (kind > 23)
+                        kind = 23;
+                     mccCheckNAddTwoStates(40, 42);
+                  }
+                  break;
+               case 0:
+                  if (curChar == 45)
+                     mccCheckNAddStates(7, 9);
+                  break;
+               case 1:
+                  if ((-9217 & l) != 0L)
+                     mccCheckNAddStates(7, 9);
+                  break;
+               case 2:
+                  if ((9216 & l) != 0L && kind > 6)
+                     kind = 6;
+                  break;
+               case 3:
+                  if (curChar == 10 && kind > 6)
+                     kind = 6;
+                  break;
+               case 4:
+                  if (curChar == 13)
+                     mccstateSet[mccnewStateCnt++] = 3;
+                  break;
+               case 6:
+                  if (curChar == 42)
+                     mccCheckNAddTwoStates(7, 8);
+                  break;
+               case 7:
+                  if ((-4398046511105 & l) != 0L)
+                     mccCheckNAddTwoStates(7, 8);
+                  break;
+               case 8:
+                  if (curChar == 42)
+                     mccCheckNAddStates(10, 12);
+                  break;
+               case 9:
+                  if ((-145135534866433 & l) != 0L)
+                     mccCheckNAddTwoStates(10, 8);
+                  break;
+               case 10:
+                  if ((-4398046511105 & l) != 0L)
+                     mccCheckNAddTwoStates(10, 8);
+                  break;
+               case 11:
+                  if (curChar == 47 && kind > 7)
+                     kind = 7;
+                  break;
+               case 12:
+                  if (curChar == 47)
+                     mccstateSet[mccnewStateCnt++] = 6;
+                  break;
+               case 13:
+                  if ((287667426198290432 & l) == 0L)
+                     break;
+                  if (kind > 21)
+                     kind = 21;
+                  mccCheckNAddTwoStates(14, 15);
+                  break;
+               case 14:
+                  if ((287948901175001088 & l) == 0L)
+                     break;
+                  if (kind > 21)
+                     kind = 21;
+                  mccCheckNAddTwoStates(14, 15);
+                  break;
+               case 16:
+                  if (curChar == 46)
+                     mccCheckNAdd(17);
+                  break;
+               case 17:
+                  if ((287948901175001088 & l) == 0L)
+                     break;
+                  if (kind > 24)
+                     kind = 24;
+                  mccCheckNAddTwoStates(17, 18);
+                  break;
+               case 19:
+                  if ((43980465111040 & l) != 0L)
+                     mccCheckNAdd(20);
+                  break;
+               case 20:
+                  if ((287948901175001088 & l) == 0L)
+                     break;
+                  if (kind > 24)
+                     kind = 24;
+                  mccCheckNAdd(20);
+                  break;
+               case 21:
+               case 22:
+                  if (curChar == 39)
+                     mccCheckNAddStates(4, 6);
+                  break;
+               case 23:
+                  if (curChar == 39)
+                     mccstateSet[mccnewStateCnt++] = 22;
+                  break;
+               case 24:
+                  if ((-549755813889 & l) != 0L)
+                     mccCheckNAddStates(4, 6);
+                  break;
+               case 25:
+                  if (curChar == 39 && kind > 26)
+                     kind = 26;
+                  break;
+               case 26:
+                  if (curChar != 36)
+                     break;
+                  if (kind > 27)
+                     kind = 27;
+                  mccCheckNAdd(27);
+                  break;
+               case 27:
+                  if ((287948969894477824 & l) == 0L)
+                     break;
+                  if (kind > 27)
+                     kind = 27;
+                  mccCheckNAdd(27);
+                  break;
+               case 28:
+                  if ((287948901175001088 & l) != 0L)
+                     mccCheckNAddStates(0, 3);
+                  break;
+               case 29:
+                  if ((287948901175001088 & l) != 0L)
+                     mccCheckNAddTwoStates(29, 30);
+                  break;
+               case 30:
+                  if (curChar != 46)
+                     break;
+                  if (kind > 24)
+                     kind = 24;
+                  mccCheckNAddTwoStates(31, 32);
+                  break;
+               case 31:
+                  if ((287948901175001088 & l) == 0L)
+                     break;
+                  if (kind > 24)
+                     kind = 24;
+                  mccCheckNAddTwoStates(31, 32);
+                  break;
+               case 33:
+                  if ((43980465111040 & l) != 0L)
+                     mccCheckNAdd(34);
+                  break;
+               case 34:
+                  if ((287948901175001088 & l) == 0L)
+                     break;
+                  if (kind > 24)
+                     kind = 24;
+                  mccCheckNAdd(34);
+                  break;
+               case 35:
+                  if ((287948901175001088 & l) != 0L)
+                     mccCheckNAddTwoStates(35, 36);
+                  break;
+               case 37:
+                  if ((43980465111040 & l) != 0L)
+                     mccCheckNAdd(38);
+                  break;
+               case 38:
+                  if ((287948901175001088 & l) == 0L)
+                     break;
+                  if (kind > 24)
+                     kind = 24;
+                  mccCheckNAdd(38);
+                  break;
+               case 39:
+                  if (curChar != 48)
+                     break;
+                  if (kind > 23)
+                     kind = 23;
+                  mccCheckNAddTwoStates(40, 42);
+                  break;
+               case 41:
+                  if ((287948901175001088 & l) == 0L)
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  mccstateSet[mccnewStateCnt++] = 41;
+                  break;
+               case 42:
+                  if ((71776119061217280 & l) == 0L)
+                     break;
+                  if (kind > 23)
+                     kind = 23;
+                  mccCheckNAdd(42);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 63);
+         do
+         {
+            switch(mccstateSet[--i])
+            {
+               case 5:
+               case 27:
+                  if ((576460745995190270 & l) == 0L)
+                     break;
+                  if (kind > 27)
+                     kind = 27;
+                  mccCheckNAdd(27);
+                  break;
+               case 1:
+                  mccAddStates(7, 9);
+                  break;
+               case 7:
+                  mccCheckNAddTwoStates(7, 8);
+                  break;
+               case 9:
+               case 10:
+                  mccCheckNAddTwoStates(10, 8);
+                  break;
+               case 15:
+                  if ((17592186048512 & l) != 0L && kind > 21)
+                     kind = 21;
+                  break;
+               case 18:
+                  if ((137438953504 & l) != 0L)
+                     mccAddStates(13, 14);
+                  break;
+               case 24:
+                  mccAddStates(4, 6);
+                  break;
+               case 32:
+                  if ((137438953504 & l) != 0L)
+                     mccAddStates(15, 16);
+                  break;
+               case 36:
+                  if ((137438953504 & l) != 0L)
+                     mccAddStates(17, 18);
+                  break;
+               case 40:
+                  if ((72057594054705152 & l) != 0L)
+                     mccCheckNAdd(41);
+                  break;
+               case 41:
+                  if ((541165879422 & l) == 0L)
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  mccCheckNAdd(41);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 63);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 63);
+         do
+         {
+            switch(mccstateSet[--i])
+            {
+               case 1:
+                  if (mccCanMove_0(hiByte, i1, i2, l1, l2))
+                     mccAddStates(7, 9);
+                  break;
+               case 7:
+                  if (mccCanMove_0(hiByte, i1, i2, l1, l2))
+                     mccCheckNAddTwoStates(7, 8);
+                  break;
+               case 9:
+               case 10:
+                  if (mccCanMove_0(hiByte, i1, i2, l1, l2))
+                     mccCheckNAddTwoStates(10, 8);
+                  break;
+               case 24:
+                  if (mccCanMove_0(hiByte, i1, i2, l1, l2))
+                     mccAddStates(4, 6);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != Int32.MaxValue)
+      {
+         mccmatchedKind = kind;
+         mccmatchedPos = curPos;
+         kind = Int32.MaxValue;
+      }
+      ++curPos;
+      if ((i = mccnewStateCnt) == (startsAt = 43 - (mccnewStateCnt = startsAt)))
+         break;
+      try { curChar = input_stream.ReadChar(); }
+      catch(System.IO.IOException) { break; }
+   }
+   if (mccmatchedPos > strPos)
+      return curPos;
+
+   int toRet = Math.Max(curPos, seenUpto);
+
+   if (curPos < toRet)
+      for (i = toRet - Math.Min(curPos, seenUpto); i-- > 0; )
+         try { curChar = input_stream.ReadChar(); }
+         catch(System.IO.IOException) { throw new Exception("Internal Error : Please send a bug report."); }
+
+   if (mccmatchedPos < strPos)
+   {
+      mccmatchedKind = strKind;
+      mccmatchedPos = strPos;
+   }
+   else if (mccmatchedPos == strPos && mccmatchedKind > strKind)
+      mccmatchedKind = strKind;
+
+   return toRet;
+}
 static readonly int[] mccnextStates = {
    29, 30, 35, 36, 23, 24, 25, 1, 2, 4, 8, 9, 11, 19, 20, 33, 
    34, 37, 38, 
-};

-private static bool mccCanMove_0(int hiByte, int i1, int i2, long l1, long l2)

-{

-   switch(hiByte)

-   {

-      case 0:

-         return ((mccbitVec2[i2] & l2) != 0L);

-      default : 

-         if ((mccbitVec0[i1] & l1) != 0L)

-            if ((mccbitVec1[i2] & l2) == 0L)

-               return false;

-            else

-            return true;

-         return false;

-   }

-}

-public static readonly string[] mccstrLiteralImages = {

-"", null, null, null, null, null, null, null, null, null, null, null, null, 

-null, null, null, null, null, null, null, null, null, null, null, null, null, null, 

-null, "=", "<>", ">", ">=", "<", "<=", "(", ",", ")", "+", "-", "*", "/", "%", };

-public static readonly string[] lexStateNames = {

-   "DEFAULT", 

-};

+};
+private static bool mccCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((mccbitVec2[i2] & l2) != 0L);
+      default : 
+         if ((mccbitVec0[i1] & l1) != 0L)
+            if ((mccbitVec1[i2] & l2) == 0L)
+               return false;
+            else
+            return true;
+         return false;
+   }
+}
+public static readonly string[] mccstrLiteralImages = {
+"", null, null, null, null, null, null, null, null, null, null, null, null, 
+null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
+null, "=", "<>", ">", ">=", "<", "<=", "(", ",", ")", "+", "-", "*", "/", "%", };
+public static readonly string[] lexStateNames = {
+   "DEFAULT", 
+};
 static readonly long[] mcctoToken = {
    4398012956417, 
-};

+};
 static readonly long[] mcctoSkip = {
    254, 
-};

+};
 static readonly long[] mcctoSpecial = {
    62, 
-};

-protected SimpleCharStream input_stream;

-private readonly int[] mccrounds = new int[43];

-private readonly int[] mccstateSet = new int[86];

-protected char curChar;

-public SelectorParserTokenManager(SimpleCharStream stream) {

-   if (SimpleCharStream.staticFlag)

-      throw new System.SystemException("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");

-   input_stream = stream;

-}

-public SelectorParserTokenManager(SimpleCharStream stream, int lexState)

-   : this(stream) {

-   SwitchTo(lexState);

-}

-public void ReInit(SimpleCharStream stream) {

-   mccmatchedPos = mccnewStateCnt = 0;

-   curLexState = defaultLexState;

-   input_stream = stream;

-   ReInitRounds();

-}

-private void ReInitRounds()

-{

-   int i;

-   mccround = -2147483647;

-   for (i = 43; i-- > 0;)

-      mccrounds[i] = Int32.MinValue;

-}

-public void ReInit(SimpleCharStream stream, int lexState) {

-   ReInit(stream);

-   SwitchTo(lexState);

-}

-public void SwitchTo(int lexState) {

-   if (lexState >= 1 || lexState < 0)

-      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.InvalidLexicalState);

-   else

-      curLexState = lexState;

-}

-

-protected Token mccFillToken()

-{

-   Token t = Token.NewToken(mccmatchedKind);

-   t.kind = mccmatchedKind;

-   string im = mccstrLiteralImages[mccmatchedKind];

-   t.image = (im == null) ? input_stream.GetImage() : im;

-   t.beginLine = input_stream.BeginLine;

-   t.beginColumn = input_stream.BeginColumn;

-   t.endLine = input_stream.EndLine;

-   t.endColumn = input_stream.EndColumn;

-   return t;

-}

-

-int curLexState = 0;

-int defaultLexState = 0;

-int mccnewStateCnt;

-int mccround;

-int mccmatchedPos;

-int mccmatchedKind;

-

-public Token GetNextToken() {

-  //int kind;

-  Token specialToken = null;

-  Token matchedToken;

-  int curPos = 0;

-

-for (;;) {

-   try {

-      curChar = input_stream.BeginToken();

-   } catch(System.IO.IOException) {

-      mccmatchedKind = 0;

-      matchedToken = mccFillToken();

-      matchedToken.specialToken = specialToken;

-      return matchedToken;

-   }

-

-   mccmatchedKind = Int32.MaxValue;

-   mccmatchedPos = 0;

-   curPos = mccMoveStringLiteralDfa0_0();

-   if (mccmatchedKind != Int32.MaxValue) {

-      if (mccmatchedPos + 1 < curPos)

-         input_stream.Backup(curPos - mccmatchedPos - 1);

-      if ((mcctoToken[mccmatchedKind >> 6] & (1L << (mccmatchedKind & 63))) != 0L) {

-         matchedToken = mccFillToken();

-         matchedToken.specialToken = specialToken;

-         return matchedToken;

-      }

-      else

-      {

-         if ((mcctoSpecial[mccmatchedKind >> 6] & (1L << (mccmatchedKind & 63))) != 0L) {

-            matchedToken = mccFillToken();

-            if (specialToken == null)

-               specialToken = matchedToken;

-            else {

-               matchedToken.specialToken = specialToken;

-               specialToken = (specialToken.next = matchedToken);

-            }

-         }

-         goto EOFLoop;

-      }

-   }

-   int error_line = input_stream.EndLine;

-   int error_column = input_stream.EndColumn;

-   string error_after = null;

-   bool EOFSeen = false;

-   try { input_stream.ReadChar(); input_stream.Backup(1); }

-   catch (System.IO.IOException) {

-      EOFSeen = true;

-      error_after = curPos <= 1 ? "" : input_stream.GetImage();

-      if (curChar == '\n' || curChar == '\r') {

-         error_line++;

-         error_column = 0;

-      } else

-         error_column++;

-   }

-   if (!EOFSeen) {

-      input_stream.Backup(1);

-      error_after = curPos <= 1 ? "" : input_stream.GetImage();

-   }

-   throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LexicalError);

-EOFLoop: ;

-  }

-}

-

-}

+};
+protected SimpleCharStream input_stream;
+private readonly int[] mccrounds = new int[43];
+private readonly int[] mccstateSet = new int[86];
+protected char curChar;
+public SelectorParserTokenManager(SimpleCharStream stream) {
+   if (SimpleCharStream.staticFlag)
+      throw new System.SystemException("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+   input_stream = stream;
+}
+public SelectorParserTokenManager(SimpleCharStream stream, int lexState)
+   : this(stream) {
+   SwitchTo(lexState);
+}
+public void ReInit(SimpleCharStream stream) {
+   mccmatchedPos = mccnewStateCnt = 0;
+   curLexState = defaultLexState;
+   input_stream = stream;
+   ReInitRounds();
+}
+private void ReInitRounds()
+{
+   int i;
+   mccround = -2147483647;
+   for (i = 43; i-- > 0;)
+      mccrounds[i] = Int32.MinValue;
+}
+public void ReInit(SimpleCharStream stream, int lexState) {
+   ReInit(stream);
+   SwitchTo(lexState);
+}
+public void SwitchTo(int lexState) {
+   if (lexState >= 1 || lexState < 0)
+      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.InvalidLexicalState);
+   else
+      curLexState = lexState;
+}
+
+protected Token mccFillToken()
+{
+   Token t = Token.NewToken(mccmatchedKind);
+   t.kind = mccmatchedKind;
+   string im = mccstrLiteralImages[mccmatchedKind];
+   t.image = (im == null) ? input_stream.GetImage() : im;
+   t.beginLine = input_stream.BeginLine;
+   t.beginColumn = input_stream.BeginColumn;
+   t.endLine = input_stream.EndLine;
+   t.endColumn = input_stream.EndColumn;
+   return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int mccnewStateCnt;
+int mccround;
+int mccmatchedPos;
+int mccmatchedKind;
+
+public Token GetNextToken() {
+  //int kind;
+  Token specialToken = null;
+  Token matchedToken;
+  int curPos = 0;
+
+for (;;) {
+   try {
+      curChar = input_stream.BeginToken();
+   } catch(System.IO.IOException) {
+      mccmatchedKind = 0;
+      matchedToken = mccFillToken();
+      matchedToken.specialToken = specialToken;
+      return matchedToken;
+   }
+
+   mccmatchedKind = Int32.MaxValue;
+   mccmatchedPos = 0;
+   curPos = mccMoveStringLiteralDfa0_0();
+   if (mccmatchedKind != Int32.MaxValue) {
+      if (mccmatchedPos + 1 < curPos)
+         input_stream.Backup(curPos - mccmatchedPos - 1);
+      if ((mcctoToken[mccmatchedKind >> 6] & (1L << (mccmatchedKind & 63))) != 0L) {
+         matchedToken = mccFillToken();
+         matchedToken.specialToken = specialToken;
+         return matchedToken;
+      }
+      else
+      {
+         if ((mcctoSpecial[mccmatchedKind >> 6] & (1L << (mccmatchedKind & 63))) != 0L) {
+            matchedToken = mccFillToken();
+            if (specialToken == null)
+               specialToken = matchedToken;
+            else {
+               matchedToken.specialToken = specialToken;
+               specialToken = (specialToken.next = matchedToken);
+            }
+         }
+         goto EOFLoop;
+      }
+   }
+   int error_line = input_stream.EndLine;
+   int error_column = input_stream.EndColumn;
+   string error_after = null;
+   bool EOFSeen = false;
+   try { input_stream.ReadChar(); input_stream.Backup(1); }
+   catch (System.IO.IOException) {
+      EOFSeen = true;
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+      if (curChar == '\n' || curChar == '\r') {
+         error_line++;
+         error_column = 0;
+      } else
+         error_column++;
+   }
+   if (!EOFSeen) {
+      input_stream.Backup(1);
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+   }
+   throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LexicalError);
+EOFLoop: ;
+  }
+}
+
+}
diff --git a/src/main/csharp/Selector/SimpleCharStream.cs b/src/main/csharp/Selector/SimpleCharStream.cs
index a49a9da..1e45359 100644
--- a/src/main/csharp/Selector/SimpleCharStream.cs
+++ b/src/main/csharp/Selector/SimpleCharStream.cs
@@ -1,366 +1,366 @@
-/* Generated By:CSharpCC: Do not edit this line. SimpleCharStream.cs Version 3.3 */

-/// <summary>

-/// An implementation of interface CharStream, where the stream is assumed to

-/// contain only ASCII characters (without unicode processing).

-/// </summary>

-

-public  class SimpleCharStream {

-  public static readonly bool staticFlag = false;

-  int bufsize;

-  int available;

-  int tokenBegin;

-  public int bufpos = -1;

-  protected int[] bufline;

-  protected int[] bufcolumn;

-

-  protected int column = 0;

-  protected int line = 1;

-

-  protected bool prevCharIsCR = false;

-  protected bool prevCharIsLF = false;

-

-  protected System.IO.TextReader inputStream;

-

-  protected char[] buffer;

-  protected int maxNextCharInd = 0;

-  protected int inBuf = 0;

-

-  protected void ExpandBuff(bool wrapAround)

-  {

-     char[] newbuffer = new char[bufsize + 2048];

-     int[] newbufline = new int[bufsize + 2048];

-     int[] newbufcolumn = new int[bufsize + 2048];

-

-     try {

-        if (wrapAround) {

-           System.Array.Copy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);

-           System.Array.Copy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);

-           buffer = newbuffer;

-

-           System.Array.Copy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);

-           System.Array.Copy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);

-           bufline = newbufline;

-

-           System.Array.Copy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);

-           System.Array.Copy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);

-           bufcolumn = newbufcolumn;

-

-           maxNextCharInd = (bufpos += (bufsize - tokenBegin));

-        } else {

-           System.Array.Copy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);

-           buffer = newbuffer;

-

-           System.Array.Copy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);

-           bufline = newbufline;

-

-           System.Array.Copy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);

-           bufcolumn = newbufcolumn;

-

-           maxNextCharInd = (bufpos -= tokenBegin);

-        }

-     } catch (System.Exception e) {

-        throw new System.SystemException(e.Message);

-     }

-

-

-     bufsize += 2048;

-     available = bufsize;

-     tokenBegin = 0;

-  }

-

-  protected void FillBuff() {

-     if (maxNextCharInd == available) {

-        if (available == bufsize) {

-           if (tokenBegin > 2048) {

-              bufpos = maxNextCharInd = 0;

-              available = tokenBegin;

-           } else if (tokenBegin < 0)

-              bufpos = maxNextCharInd = 0;

-           else

-              ExpandBuff(false);

-        } else if (available > tokenBegin)

-           available = bufsize;

-        else if ((tokenBegin - available) < 2048)

-           ExpandBuff(true);

-        else

-           available = tokenBegin;

-     }

-

-     int i;

-     try {

-        if ((i = inputStream.Read(buffer, maxNextCharInd,

-                                    available - maxNextCharInd)) == -1) {

-           inputStream.Close();

-           throw new System.IO.IOException();

-        } else

-           maxNextCharInd += i;

-        return;

-     } catch(System.IO.IOException e) {

-        --bufpos;

-        Backup(0);

-        if (tokenBegin == -1)

-           tokenBegin = bufpos;

-        throw e;

-     }

-  }

-

-  public char BeginToken() {

-     tokenBegin = -1;

-     try {

-         char c = ReadChar();

-         tokenBegin = bufpos;

-         return c;

-     } catch (System.IO.EndOfStreamException e) {

-         if (tokenBegin == -1)

-             tokenBegin = bufpos;

-         throw e;

-     }

-  }

-

-  protected void UpdateLineColumn(char c) {

-     column++;

-

-     if (prevCharIsLF) {

-        prevCharIsLF = false;

-        line += (column = 1);

-     } else if (prevCharIsCR) {

-        prevCharIsCR = false;

-        if (c == '\n') {

-           prevCharIsLF = true;

-        } else

-           line += (column = 1);

-     }

-

-     switch (c) {

-        case '\r' :

-           prevCharIsCR = true;

-           break;

-        case '\n' :

-           prevCharIsLF = true;

-           break;

-        case '\t' :

-           column--;

-           column += (8 - (column & 07));

-           break;

-        default :

-           break;

-     }

-

-     bufline[bufpos] = line;

-     bufcolumn[bufpos] = column;

-  }

-

-  public char ReadChar() {

-     if (inBuf > 0) {

-        --inBuf;

-

-        if (++bufpos == bufsize)

-           bufpos = 0;

-

-        return buffer[bufpos];

-     }

-

-     if (++bufpos >= maxNextCharInd)

-        FillBuff();

-     if (bufpos >= maxNextCharInd) {

-        bufpos--;

-        if (bufpos < 0)

-            bufpos += bufsize;

-        throw new System.IO.EndOfStreamException();

-     }

-

-     char c = buffer[bufpos];

-

-     UpdateLineColumn(c);

-     return (c);

-  }

-

-[System.Obsolete("Deprecated - use EndColumn instead.", false)]

-

-  public int Column {

-  get {

-       return bufcolumn[bufpos];

-    }

-  }

-

-[System.Obsolete("Deprecated - use EndLine instead.", false)]

-

-  public int Line {

-  get {

-       return bufline[bufpos];

-    }

-  }

-

-  public int EndColumn {

-  get {

-       return bufcolumn[bufpos];

-    }

-  }

-

-  public int EndLine {

-  get {

-       return bufline[bufpos];

-    }

-  }

-

-  public int BeginColumn {

-  get {

-       return bufcolumn[tokenBegin];

-    }

-  }

-

-  public int BeginLine {

-  get {

-       return bufline[tokenBegin];

-    }

-  }

-

-  public void Backup(int amount) {

-

-    inBuf += amount;

-    if ((bufpos -= amount) < 0)

-       bufpos += bufsize;

-  }

-

-  public SimpleCharStream(System.IO.TextReader dstream, int startline,

-  int startcolumn, int buffersize) {

-    inputStream = dstream;

-    line = startline;

-    column = startcolumn - 1;

-

-    available = bufsize = buffersize;

-    buffer = new char[buffersize];

-    bufline = new int[buffersize];

-    bufcolumn = new int[buffersize];

-  }

-

-  public SimpleCharStream(System.IO.TextReader dstream, int startline,

-                                                           int startcolumn) : 

-     this(dstream, startline, startcolumn, 4096) {

-  }

-

-  public SimpleCharStream(System.IO.TextReader dstream) :

-     this(dstream, 1, 1, 4096) {

-  }

-  public void ReInit(System.IO.TextReader dstream, int startline,

-  int startcolumn, int buffersize) {

-    inputStream = dstream;

-    line = startline;

-    column = startcolumn - 1;

-

-    if (buffer == null || buffersize != buffer.Length) {

-      available = bufsize = buffersize;

-      buffer = new char[buffersize];

-      bufline = new int[buffersize];

-      bufcolumn = new int[buffersize];

-    }

-    prevCharIsLF = prevCharIsCR = false;

-    tokenBegin = inBuf = maxNextCharInd = 0;

-    bufpos = -1;

-  }

-

-  public void ReInit(System.IO.TextReader dstream, int startline,

-                                                           int startcolumn) {

-     ReInit(dstream, startline, startcolumn, 4096);

-  }

-

-  public void ReInit(System.IO.TextReader dstream) {

-     ReInit(dstream, 1, 1, 4096);

-  }

-  public SimpleCharStream(System.IO.Stream dstream, int startline,

-  int startcolumn, int buffersize) :

-     this(new System.IO.StreamReader(dstream), startline, startcolumn, 4096) {

-  }

-

-  public SimpleCharStream(System.IO.Stream dstream, int startline,

-                                                           int startcolumn) :

-     this(dstream, startline, startcolumn, 4096) {

-  }

-

-  public SimpleCharStream(System.IO.Stream dstream) :

-     this(dstream, 1, 1, 4096) {

-  }

-

-  public void ReInit(System.IO.Stream dstream, int startline,

-                          int startcolumn, int buffersize) {

-     ReInit(new System.IO.StreamReader(dstream), startline, startcolumn, 4096);

-  }

-

-  public void ReInit(System.IO.Stream dstream) {

-     ReInit(dstream, 1, 1, 4096);

-  }

-  public void ReInit(System.IO.Stream dstream, int startline,

-                                                           int startcolumn) {

-     ReInit(dstream, startline, startcolumn, 4096);

-  }

-  public string GetImage() {

-     if (bufpos >= tokenBegin)

-        return new string(buffer, tokenBegin, bufpos - tokenBegin + 1);

-     else

-        return new string(buffer, tokenBegin, bufsize - tokenBegin) +

-                              new string(buffer, 0, bufpos + 1);

-  }

-

-  public char[] GetSuffix(int len) {

-     char[] ret = new char[len];

-

-     if ((bufpos + 1) >= len)

-        System.Array.Copy(buffer, bufpos - len + 1, ret, 0, len);

-     else {

-        System.Array.Copy(buffer, bufsize - (len - bufpos - 1), ret, 0,

-                                                          len - bufpos - 1);

-        System.Array.Copy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);

-     }

-

-     return ret;

-  }

-

-  public void Done()

-  {

-     buffer = null;

-     bufline = null;

-     bufcolumn = null;

-  }

-

-  /// <summary>

-  /// Method to adjust line and column numbers for the start of a token.

-  /// </summary>

-  public void AdjustBeginLineColumn(int newLine, int newCol) {

-     int start = tokenBegin;

-     int len;

-

-     if (bufpos >= tokenBegin) {

-        len = bufpos - tokenBegin + inBuf + 1;

-     } else {

-        len = bufsize - tokenBegin + bufpos + 1 + inBuf;

-     }

-

-     int i = 0, j = 0, k = 0;

-     int nextColDiff = 0, columnDiff = 0;

-

-     while (i < len &&

-            bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) {

-        bufline[j] = newLine;

-        nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];

-        bufcolumn[j] = newCol + columnDiff;

-        columnDiff = nextColDiff;

-        i++;

-     } 

-

-     if (i < len) {

-        bufline[j] = newLine++;

-        bufcolumn[j] = newCol + columnDiff;

-

-        while (i++ < len) {

-           if (bufline[j = start % bufsize] != bufline[++start % bufsize])

-              bufline[j] = newLine++;

-           else

-              bufline[j] = newLine;

-        }

-     }

-

-     line = bufline[j];

-     column = bufcolumn[j];

-  }

-

-}

+/* Generated By:CSharpCC: Do not edit this charLine. SimpleCharStream.cs Version 3.3 */
+/// <summary>
+/// An implementation of interface CharStream, where the stream is assumed to
+/// contain only ASCII characters (without unicode processing).
+/// </summary>
+
+public  class SimpleCharStream {
+  public static readonly bool staticFlag = false;
+  int bufsize;
+  int available;
+  int tokenBegin;
+  public int bufpos = -1;
+  protected int[] bufline;
+  protected int[] bufcolumn;
+
+  protected int charColumn = 0;
+  protected int charLine = 1;
+
+  protected bool prevCharIsCR = false;
+  protected bool prevCharIsLF = false;
+
+  protected System.IO.TextReader inputStream;
+
+  protected char[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int inBuf = 0;
+
+  protected void ExpandBuff(bool wrapAround)
+  {
+     char[] newbuffer = new char[bufsize + 2048];
+     int[] newbufline = new int[bufsize + 2048];
+     int[] newbufcolumn = new int[bufsize + 2048];
+
+     try {
+        if (wrapAround) {
+           System.Array.Copy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+           System.Array.Copy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+           buffer = newbuffer;
+
+           System.Array.Copy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+           System.Array.Copy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+           bufline = newbufline;
+
+           System.Array.Copy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+           System.Array.Copy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+           bufcolumn = newbufcolumn;
+
+           maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+        } else {
+           System.Array.Copy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+           buffer = newbuffer;
+
+           System.Array.Copy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+           bufline = newbufline;
+
+           System.Array.Copy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+           bufcolumn = newbufcolumn;
+
+           maxNextCharInd = (bufpos -= tokenBegin);
+        }
+     } catch (System.Exception e) {
+        throw new System.SystemException(e.Message);
+     }
+
+
+     bufsize += 2048;
+     available = bufsize;
+     tokenBegin = 0;
+  }
+
+  protected void FillBuff() {
+     if (maxNextCharInd == available) {
+        if (available == bufsize) {
+           if (tokenBegin > 2048) {
+              bufpos = maxNextCharInd = 0;
+              available = tokenBegin;
+           } else if (tokenBegin < 0)
+              bufpos = maxNextCharInd = 0;
+           else
+              ExpandBuff(false);
+        } else if (available > tokenBegin)
+           available = bufsize;
+        else if ((tokenBegin - available) < 2048)
+           ExpandBuff(true);
+        else
+           available = tokenBegin;
+     }
+
+     int i;
+     try {
+        if ((i = inputStream.Read(buffer, maxNextCharInd,
+                                    available - maxNextCharInd)) == -1) {
+           inputStream.Close();
+           throw new System.IO.IOException();
+        } else
+           maxNextCharInd += i;
+        return;
+     } catch(System.IO.IOException e) {
+        --bufpos;
+        Backup(0);
+        if (tokenBegin == -1)
+           tokenBegin = bufpos;
+        throw e;
+     }
+  }
+
+  public char BeginToken() {
+     tokenBegin = -1;
+     try {
+         char c = ReadChar();
+         tokenBegin = bufpos;
+         return c;
+     } catch (System.IO.EndOfStreamException e) {
+         if (tokenBegin == -1)
+             tokenBegin = bufpos;
+         throw e;
+     }
+  }
+
+  protected void UpdateLineColumn(char c) {
+     charColumn++;
+
+     if (prevCharIsLF) {
+        prevCharIsLF = false;
+        charLine += (charColumn = 1);
+     } else if (prevCharIsCR) {
+        prevCharIsCR = false;
+        if (c == '\n') {
+           prevCharIsLF = true;
+        } else
+           charLine += (charColumn = 1);
+     }
+
+     switch (c) {
+        case '\r' :
+           prevCharIsCR = true;
+           break;
+        case '\n' :
+           prevCharIsLF = true;
+           break;
+        case '\t' :
+           charColumn--;
+           charColumn += (8 - (charColumn & 07));
+           break;
+        default :
+           break;
+     }
+
+     bufline[bufpos] = charLine;
+     bufcolumn[bufpos] = charColumn;
+  }
+
+  public char ReadChar() {
+     if (inBuf > 0) {
+        --inBuf;
+
+        if (++bufpos == bufsize)
+           bufpos = 0;
+
+        return buffer[bufpos];
+     }
+
+     if (++bufpos >= maxNextCharInd)
+        FillBuff();
+     if (bufpos >= maxNextCharInd) {
+        bufpos--;
+        if (bufpos < 0)
+            bufpos += bufsize;
+        throw new System.IO.EndOfStreamException();
+     }
+
+     char c = buffer[bufpos];
+
+     UpdateLineColumn(c);
+     return (c);
+  }
+
+[System.Obsolete("Deprecated - use EndColumn instead.", false)]
+
+  public int Column {
+  get {
+       return bufcolumn[bufpos];
+    }
+  }
+
+[System.Obsolete("Deprecated - use EndLine instead.", false)]
+
+  public int Line {
+  get {
+       return bufline[bufpos];
+    }
+  }
+
+  public int EndColumn {
+  get {
+       return bufcolumn[bufpos];
+    }
+  }
+
+  public int EndLine {
+  get {
+       return bufline[bufpos];
+    }
+  }
+
+  public int BeginColumn {
+  get {
+       return bufcolumn[tokenBegin];
+    }
+  }
+
+  public int BeginLine {
+  get {
+       return bufline[tokenBegin];
+    }
+  }
+
+  public void Backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+       bufpos += bufsize;
+  }
+
+  public SimpleCharStream(System.IO.TextReader dstream, int startline,
+  int startcolumn, int buffersize) {
+    inputStream = dstream;
+    charLine = startline;
+    charColumn = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+  }
+
+  public SimpleCharStream(System.IO.TextReader dstream, int startline,
+                                                           int startcolumn) : 
+     this(dstream, startline, startcolumn, 4096) {
+  }
+
+  public SimpleCharStream(System.IO.TextReader dstream) :
+     this(dstream, 1, 1, 4096) {
+  }
+  public void ReInit(System.IO.TextReader dstream, int startline,
+  int startcolumn, int buffersize) {
+    inputStream = dstream;
+    charLine = startline;
+    charColumn = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.Length) {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    bufpos = -1;
+  }
+
+  public void ReInit(System.IO.TextReader dstream, int startline,
+                                                           int startcolumn) {
+     ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  public void ReInit(System.IO.TextReader dstream) {
+     ReInit(dstream, 1, 1, 4096);
+  }
+  public SimpleCharStream(System.IO.Stream dstream, int startline,
+  int startcolumn, int buffersize) :
+     this(new System.IO.StreamReader(dstream), startline, startcolumn, 4096) {
+  }
+
+  public SimpleCharStream(System.IO.Stream dstream, int startline,
+                                                           int startcolumn) :
+     this(dstream, startline, startcolumn, 4096) {
+  }
+
+  public SimpleCharStream(System.IO.Stream dstream) :
+     this(dstream, 1, 1, 4096) {
+  }
+
+  public void ReInit(System.IO.Stream dstream, int startline,
+                          int startcolumn, int buffersize) {
+     ReInit(new System.IO.StreamReader(dstream), startline, startcolumn, 4096);
+  }
+
+  public void ReInit(System.IO.Stream dstream) {
+     ReInit(dstream, 1, 1, 4096);
+  }
+  public void ReInit(System.IO.Stream dstream, int startline,
+                                                           int startcolumn) {
+     ReInit(dstream, startline, startcolumn, 4096);
+  }
+  public string GetImage() {
+     if (bufpos >= tokenBegin)
+        return new string(buffer, tokenBegin, bufpos - tokenBegin + 1);
+     else
+        return new string(buffer, tokenBegin, bufsize - tokenBegin) +
+                              new string(buffer, 0, bufpos + 1);
+  }
+
+  public char[] GetSuffix(int len) {
+     char[] ret = new char[len];
+
+     if ((bufpos + 1) >= len)
+        System.Array.Copy(buffer, bufpos - len + 1, ret, 0, len);
+     else {
+        System.Array.Copy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                          len - bufpos - 1);
+        System.Array.Copy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+     }
+
+     return ret;
+  }
+
+  public void Done()
+  {
+     buffer = null;
+     bufline = null;
+     bufcolumn = null;
+  }
+
+  /// <summary>
+  /// Method to adjust charLine and charColumn numbers for the start of a token.
+  /// </summary>
+  public void AdjustBeginLineColumn(int newLine, int newCol) {
+     int start = tokenBegin;
+     int len;
+
+     if (bufpos >= tokenBegin) {
+        len = bufpos - tokenBegin + inBuf + 1;
+     } else {
+        len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+     }
+
+     int i = 0, j = 0, k = 0;
+     int nextColDiff = 0, columnDiff = 0;
+
+     while (i < len &&
+            bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) {
+        bufline[j] = newLine;
+        nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+        bufcolumn[j] = newCol + columnDiff;
+        columnDiff = nextColDiff;
+        i++;
+     } 
+
+     if (i < len) {
+        bufline[j] = newLine++;
+        bufcolumn[j] = newCol + columnDiff;
+
+        while (i++ < len) {
+           if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+              bufline[j] = newLine++;
+           else
+              bufline[j] = newLine;
+        }
+     }
+
+     charLine = bufline[j];
+     charColumn = bufcolumn[j];
+  }
+
+}
diff --git a/src/main/csharp/Selector/Token.cs b/src/main/csharp/Selector/Token.cs
index bc5b705..49bc4ea 100644
--- a/src/main/csharp/Selector/Token.cs
+++ b/src/main/csharp/Selector/Token.cs
@@ -1,78 +1,78 @@
-/* Generated By:CSharpCC: Do not edit this line. Token.cs Version 3.0 */

-/// <summary>

-/// Describes the input token stream.

-/// </summary>

-

-public  class Token {

-

-  /// <summary>

-  /// Gets an integer that describes the kind of this token.

-  /// </summary>

-  /// <remarks>

-  /// This numbering system is determined by CSharpCCParser, and 

-  /// a table of these numbers is stored in the class <see cref="SelectorParserConstants"/>.

-  /// </remarks>

-  public int kind;

-

-  /**

-   * beginLine and beginColumn describe the position of the first character

-   * of this token; endLine and endColumn describe the position of the

-   * last character of this token.

-   */

-  public int beginLine, beginColumn, endLine, endColumn;

-

-  /**

-   * The string image of the token.

-   */

-  public string image;

-

-  /**

-   * A reference to the next regular (non-special) token from the input

-   * stream.  If this is the last token from the input stream, or if the

-   * token manager has not read tokens beyond this one, this field is

-   * set to null.  This is true only if this token is also a regular

-   * token.  Otherwise, see below for a description of the contents of

-   * this field.

-   */

-  public Token next;

-

-  /**

-   * This field is used to access special tokens that occur prior to this

-   * token, but after the immediately preceding regular (non-special) token.

-   * If there are no such special tokens, this field is set to null.

-   * When there are more than one such special token, this field refers

-   * to the last of these special tokens, which in turn refers to the next

-   * previous special token through its specialToken field, and so on

-   * until the first special token (whose specialToken field is null).

-   * The next fields of special tokens refer to other special tokens that

-   * immediately follow it (without an intervening regular token).  If there

-   * is no such token, this field is null.

-   */

-  public Token specialToken;

-

-  /**

-   * Returns the image.

-   */

-  public override string ToString() {

-     return image;

-  }

-

-  /**

-   * Returns a new Token object, by default. However, if you want, you

-   * can create and return subclass objects based on the value of ofKind.

-   * Simply add the cases to the switch for all those special cases.

-   * For example, if you have a subclass of Token called IDToken that

-   * you want to create if ofKind is ID, simlpy add something like :

-   *

-   *    case MyParserConstants.ID : return new IDToken();

-   *

-   * to the following switch statement. Then you can cast matchedToken

-   * variable to the appropriate type and use it in your lexical actions.

-   */

-  public static Token NewToken(int ofKind) {

-     switch(ofKind) {

-       default : return new Token();

-     }

-  }

-

-}

+/* Generated By:CSharpCC: Do not edit this line. Token.cs Version 3.0 */
+/// <summary>
+/// Describes the input token stream.
+/// </summary>
+
+public  class Token {
+
+  /// <summary>
+  /// Gets an integer that describes the kind of this token.
+  /// </summary>
+  /// <remarks>
+  /// This numbering system is determined by CSharpCCParser, and 
+  /// a table of these numbers is stored in the class <see cref="SelectorParserConstants"/>.
+  /// </remarks>
+  public int kind;
+
+  /**
+   * beginLine and beginColumn describe the position of the first character
+   * of this token; endLine and endColumn describe the position of the
+   * last character of this token.
+   */
+  public int beginLine, beginColumn, endLine, endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public string image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * Returns the image.
+   */
+  public override string ToString() {
+     return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simlpy add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken();
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use it in your lexical actions.
+   */
+  public static Token NewToken(int ofKind) {
+     switch(ofKind) {
+       default : return new Token();
+     }
+  }
+
+}
diff --git a/src/main/csharp/Selector/TokenMgrError.cs b/src/main/csharp/Selector/TokenMgrError.cs
index b011703..f525134 100644
--- a/src/main/csharp/Selector/TokenMgrError.cs
+++ b/src/main/csharp/Selector/TokenMgrError.cs
@@ -1,130 +1,130 @@
-/* Generated By:CSharpCC: Do not edit this line. TokenMgrError.cs Version 3.0 */

-public  class TokenMgrError : System.SystemException

-{

-   /*

-    * Ordinals for various reasons why an Exceptions of this type can be thrown.

-    */

-

-   /**

-    * Lexical error occured.

-    */

-   internal static readonly int LexicalError = 0;

-

-   /**

-    * An attempt wass made to create a second instance of a static token manager.

-    */

-   internal static readonly int StaticLexerError = 1;

-

-   /**

-    * Tried to change to an invalid lexical state.

-    */

-   internal static readonly int InvalidLexicalState = 2;

-

-   /**

-    * Detected (and bailed out of) an infinite loop in the token manager.

-    */

-   internal static readonly int LoopDetected = 3;

-

-   /**

-    * Indicates the reason why the exception is thrown. It will have

-    * one of the above 4 values.

-    */

-   int errorCode;

-

-   /**

-    * Replaces unprintable characters by their espaced (or unicode escaped)

-    * equivalents in the given string

-    */

-   protected static string AddEscapes(string str) {

-      System.Text.StringBuilder retval = new System.Text.StringBuilder();

-      char ch;

-      for (int i = 0; i < str.Length; i++) {

-        switch (str[i]) {

-           case '\0' :

-              continue;

-           case '\b':

-              retval.Append("\\b");

-              continue;

-           case '\t':

-              retval.Append("\\t");

-              continue;

-           case '\n':

-              retval.Append("\\n");

-              continue;

-           case '\f':

-              retval.Append("\\f");

-              continue;

-           case '\r':

-              retval.Append("\\r");

-              continue;

-           case '\"':

-              retval.Append("\\\"");

-              continue;

-           case '\'':

-              retval.Append("\\\'");

-              continue;

-           case '\\':

-              retval.Append("\\\\");

-              continue;

-           default:

-              if ((ch = str[i]) < 0x20 || ch > 0x7e) {

-                 string s = "0000" + System.Convert.ToString((int)ch, 16);

-                 retval.Append("\\u" + s.Substring(s.Length - 4, s.Length - (s.Length - 4)));

-              } else {

-                 retval.Append(ch);

-              }

-              continue;

-        }

-      }

-      return retval.ToString();

-   }

-

-   /**

-    * Returns a detailed message for the Exception when it is thrown by the

-    * token manager to indicate a lexical error.

-    * Parameters : 

-    *    EOFSeen     : indicates if EOF caused the lexicl error

-    *    curLexState : lexical state in which this error occured

-    *    errorLine   : line number when the error occured

-    *    errorColumn : column number when the error occured

-    *    errorAfter  : prefix that was seen before this error occured

-    *    curchar     : the offending character

-    * Note: You can customize the lexical error message by modifying this method.

-    */

-   protected static string GetLexicalError(bool EOFSeen, int lexState, int errorLine, int errorColumn, string errorAfter, char curChar) {

-      return("Lexical error at line " +

-           errorLine + ", column " +

-           errorColumn + ".  Encountered: " +

-           (EOFSeen ? "<EOF> " : ("\"" + AddEscapes(curChar.ToString()) + "\"") + " (" + (int)curChar + "), ") +

-           "after : \"" + AddEscapes(errorAfter) + "\"");

-   }

-

-   /**

-    * You can also modify the body of this method to customize your error messages.

-    * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not

-    * of end-users concern, so you can return something like : 

-    *

-    *     "Internal Error : Please file a bug report .... "

-    *

-    * from this method for such cases in the release version of your parser.

-    */

-   public override string Message {

-      get { return base.Message; }

-   }

-

-   /*

-    * Constructors of various flavors follow.

-    */

-

-   public TokenMgrError() {

-   }

-

-   public TokenMgrError(string message, int reason) :

-      base(message) {

-      errorCode = reason;

-   }

-

-   public TokenMgrError(bool EOFSeen, int lexState, int errorLine, int errorColumn, string errorAfter, char curChar, int reason) :

-      this(GetLexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason) {

-   }

-}

+/* Generated By:CSharpCC: Do not edit this line. TokenMgrError.cs Version 3.0 */
+public  class TokenMgrError : System.SystemException
+{
+   /*
+    * Ordinals for various reasons why an Exceptions of this type can be thrown.
+    */
+
+   /*
+    * Lexical error occured.
+    */
+   internal static readonly int LexicalError = 0;
+
+   /*
+    * An attempt wass made to create a second instance of a static token manager.
+    */
+   internal static readonly int StaticLexerError = 1;
+
+   /*
+    * Tried to change to an invalid lexical state.
+    */
+   internal static readonly int InvalidLexicalState = 2;
+
+   /*
+    * Detected (and bailed out of) an infinite loop in the token manager.
+    */
+   internal static readonly int LoopDetected = 3;
+
+   /*
+    * Indicates the reason why the exception is thrown. It will have
+    * one of the above 4 values.
+    */
+   int errorCode;
+
+   /*
+    * Replaces unprintable characters by their espaced (or unicode escaped)
+    * equivalents in the given string
+    */
+   protected static string AddEscapes(string str) {
+      System.Text.StringBuilder retval = new System.Text.StringBuilder();
+      char ch;
+      for (int i = 0; i < str.Length; i++) {
+        switch (str[i]) {
+           case '\0' :
+              continue;
+           case '\b':
+              retval.Append("\\b");
+              continue;
+           case '\t':
+              retval.Append("\\t");
+              continue;
+           case '\n':
+              retval.Append("\\n");
+              continue;
+           case '\f':
+              retval.Append("\\f");
+              continue;
+           case '\r':
+              retval.Append("\\r");
+              continue;
+           case '\"':
+              retval.Append("\\\"");
+              continue;
+           case '\'':
+              retval.Append("\\\'");
+              continue;
+           case '\\':
+              retval.Append("\\\\");
+              continue;
+           default:
+              if ((ch = str[i]) < 0x20 || ch > 0x7e) {
+                 string s = "0000" + System.Convert.ToString((int)ch, 16);
+                 retval.Append("\\u" + s.Substring(s.Length - 4, s.Length - (s.Length - 4)));
+              } else {
+                 retval.Append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.ToString();
+   }
+
+   /*
+    * Returns a detailed message for the Exception when it is thrown by the
+    * token manager to indicate a lexical error.
+    * Parameters : 
+    *    EOFSeen     : indicates if EOF caused the lexicl error
+    *    curLexState : lexical state in which this error occured
+    *    errorLine   : line number when the error occured
+    *    errorColumn : column number when the error occured
+    *    errorAfter  : prefix that was seen before this error occured
+    *    curchar     : the offending character
+    * Note: You can customize the lexical error message by modifying this method.
+    */
+   protected static string GetLexicalError(bool EOFSeen, int lexState, int errorLine, int errorColumn, string errorAfter, char curChar) {
+      return("Lexical error at line " +
+           errorLine + ", column " +
+           errorColumn + ".  Encountered: " +
+           (EOFSeen ? "<EOF> " : ("\"" + AddEscapes(curChar.ToString()) + "\"") + " (" + (int)curChar + "), ") +
+           "after : \"" + AddEscapes(errorAfter) + "\"");
+   }
+
+   /*
+    * You can also modify the body of this method to customize your error messages.
+    * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+    * of end-users concern, so you can return something like : 
+    *
+    *     "Internal Error : Please file a bug report .... "
+    *
+    * from this method for such cases in the release version of your parser.
+    */
+   public override string Message {
+      get { return base.Message; }
+   }
+
+   /*
+    * Constructors of various flavors follow.
+    */
+
+   public TokenMgrError() {
+   }
+
+   public TokenMgrError(string message, int reason) :
+      base(message) {
+      errorCode = reason;
+   }
+
+   public TokenMgrError(bool EOFSeen, int lexState, int errorLine, int errorColumn, string errorAfter, char curChar, int reason) :
+      this(GetLexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason) {
+   }
+}
diff --git a/src/main/csharp/Selector/UnaryExpression.cs b/src/main/csharp/Selector/UnaryExpression.cs
index 4ccbbc0..14d0262 100644
--- a/src/main/csharp/Selector/UnaryExpression.cs
+++ b/src/main/csharp/Selector/UnaryExpression.cs
@@ -1,66 +1,65 @@
-using System;

-/**

- *

- * Licensed to the Apache Software Foundation (ASF) under one or more

- * contributor license agreements.  See the NOTICE file distributed with

- * this work for additional information regarding copyright ownership.

- * The ASF licenses this file to You under the Apache License, Version 2.0

- * (the "License"); you may not use this file except in compliance with

- * the License.  You may obtain a copy of the License at

- *

- * http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-namespace Apache.NMS.Selector

-{

-    /// <summary>

-    /// An expression which performs an operation on one expression value.

-    /// </summary>

-    public abstract class UnaryExpression : IExpression

-    {

-        protected IExpression rightExpression;

-        public IExpression Right

-        {

-            get { return rightExpression; }

-            set { rightExpression = value; }

-        }

-

-        protected abstract string ExpressionSymbol

-        {

-            get;

-        }

-

-        public UnaryExpression(IExpression left)

-        {

-            this.rightExpression = left;

-        }

-

-        public abstract object Evaluate(MessageEvaluationContext message);

-

-        public override string ToString()

-        {

-            return "(" + ExpressionSymbol + " " + rightExpression.ToString() + ")";

-        }

-

-        public static IExpression CreateNegate(IExpression left)

-        {

-            return new NegateExpression(left);

-        }

-

-        public static IBooleanExpression CreateNOT(IBooleanExpression left)

-        {

-            return new NOTExpression(left);

-        }

-

-        public static IBooleanExpression CreateBooleanCast(IExpression left)

-        {

-            return new BooleanCastExpression(left);

-        }

-    }

-}

+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Selector
+{
+    /// <summary>
+    /// An expression which performs an operation on one expression value.
+    /// </summary>
+    public abstract class UnaryExpression : IExpression
+    {
+        protected IExpression rightExpression;
+        public IExpression Right
+        {
+            get { return rightExpression; }
+            set { rightExpression = value; }
+        }
+
+        protected abstract string ExpressionSymbol
+        {
+            get;
+        }
+
+        public UnaryExpression(IExpression left)
+        {
+            this.rightExpression = left;
+        }
+
+        public abstract object Evaluate(MessageEvaluationContext message);
+
+        public override string ToString()
+        {
+            return "(" + ExpressionSymbol + " " + rightExpression.ToString() + ")";
+        }
+
+        public static IExpression CreateNegate(IExpression left)
+        {
+            return new NegateExpression(left);
+        }
+
+        public static IBooleanExpression CreateNOT(IBooleanExpression left)
+        {
+            return new NOTExpression(left);
+        }
+
+        public static IBooleanExpression CreateBooleanCast(IExpression left)
+        {
+            return new BooleanCastExpression(left);
+        }
+    }
+}
diff --git a/src/main/csharp/Session.cs b/src/main/csharp/Session.cs
index b64c6ae..531dce2 100644
--- a/src/main/csharp/Session.cs
+++ b/src/main/csharp/Session.cs
@@ -70,6 +70,12 @@
 
         public IMessageConsumer CreateConsumer(IDestination destination, string selector, bool noLocal)
         {
+            // Bad consumer test
+            if(destination == null)
+            {
+                throw new NMSException("Consumer destination cannot be null");
+            }
+
             MessageQueue queue = MessageConverter.ToMsmqDestination(destination);
             return new MessageConsumer(this, acknowledgementMode, queue, selector);
         }
@@ -178,6 +184,9 @@
                 throw new InvalidOperationException("You cannot perform a Commit() on a non-transacted session. Acknowlegement mode is: " + acknowledgementMode);
             }
             messageQueueTransaction.Commit();
+
+            // Start a new transaction
+            MessageQueueTransaction = new MessageQueueTransaction();
         }
 
         public void Rollback()
@@ -187,6 +196,9 @@
                 throw new InvalidOperationException("You cannot perform a Commit() on a non-transacted session. Acknowlegement mode is: " + acknowledgementMode);
             }
             messageQueueTransaction.Abort();
+
+            // Start a new transaction
+            MessageQueueTransaction = new MessageQueueTransaction();
         }
 
         public void Recover()
@@ -221,17 +233,17 @@
 
         public MessageQueueTransaction MessageQueueTransaction
         {
-            get
+            get { return messageQueueTransaction; }
+            set
             {
+                messageQueueTransaction = value;
+
                 if(null != messageQueueTransaction
                     && messageQueueTransaction.Status != MessageQueueTransactionStatus.Pending)
                 {
                     messageQueueTransaction.Begin();
                 }
-
-                return messageQueueTransaction;
             }
-            set { messageQueueTransaction = value; }
         }
 
         public IMessageConverter MessageConverter
diff --git a/src/test/csharp/AsyncConsumeTest.cs b/src/test/csharp/AsyncConsumeTest.cs
new file mode 100644
index 0000000..4d38b1a
--- /dev/null
+++ b/src/test/csharp/AsyncConsumeTest.cs
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System.Threading;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class AsyncConsumeTest : NMSTest
+	{
+		protected string RESPONSE_CLIENT_ID;
+		protected AutoResetEvent semaphore;
+		protected bool received;
+		protected IMessage receivedMsg;
+
+		public AsyncConsumeTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[SetUp]
+		public override void SetUp()
+		{
+			base.SetUp();
+			semaphore = new AutoResetEvent(false);
+			received = false;
+			receivedMsg = null;
+
+			RESPONSE_CLIENT_ID = GetTestClientId() + ":RESPONSE";
+		}
+
+		//[TearDown]
+		public override void TearDown()
+		{
+			receivedMsg = null;
+			base.TearDown();
+		}
+
+		//[Test]
+		public virtual void TestAsynchronousConsume(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			// IBM WMQ doesn't support both synchronous and asynchronous operations
+			// in the same session. Needs 2 separate sessions.
+			using(IConnection connection = CreateConnectionAndStart(GetTestClientId()))
+			using(ISession producerSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(ISession consumerSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(IDestination producerDestination = GetClearDestinationByNodeReference(producerSession, testDestRef))
+			using(IDestination consumerDestination = GetClearDestinationByNodeReference(consumerSession, testDestRef))
+			using(IMessageConsumer consumer = consumerSession.CreateConsumer(consumerDestination))
+			using(IMessageProducer producer = producerSession.CreateProducer(producerDestination))
+			{
+				producer.DeliveryMode = deliveryMode;
+				consumer.Listener += new MessageListener(OnMessage);
+
+				IMessage request = producerSession.CreateMessage();
+				request.NMSCorrelationID = "AsyncConsume";
+				request.NMSType = "Test";
+				producer.Send(request);
+
+				WaitForMessageToArrive();
+				Assert.AreEqual(request.NMSCorrelationID, receivedMsg.NMSCorrelationID, "Invalid correlation ID.");
+			}
+		}
+
+		//[Test]
+		public virtual void TestCreateConsumerAfterSend(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnectionAndStart(GetTestClientId()))
+			using(ISession producerSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(ISession consumerSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(IDestination producerDestination = GetClearDestinationByNodeReference(producerSession, testDestRef))
+			using(IDestination consumerDestination = GetDestinationByNodeReference(consumerSession, testDestRef))
+			{
+				string correlationId = "AsyncConsumeAfterSend";
+
+				using(IMessageProducer producer = producerSession.CreateProducer(producerDestination))
+				{
+					producer.DeliveryMode = deliveryMode;
+					IMessage request = producerSession.CreateMessage();
+					request.NMSCorrelationID = correlationId;
+					request.NMSType = "Test";
+					producer.Send(request);
+				}
+
+				using(IMessageConsumer consumer = consumerSession.CreateConsumer(consumerDestination))
+				{
+					consumer.Listener += new MessageListener(OnMessage);
+					WaitForMessageToArrive();
+					Assert.AreEqual(correlationId, receivedMsg.NMSCorrelationID, "Invalid correlation ID.");
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestCreateConsumerBeforeSendAddListenerAfterSend(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnectionAndStart(GetTestClientId()))
+			using(ISession producerSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(ISession consumerSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(IDestination producerDestination = GetClearDestinationByNodeReference(producerSession, testDestRef))
+			using(IDestination consumerDestination = GetDestinationByNodeReference(consumerSession, testDestRef))
+			using(IMessageConsumer consumer = consumerSession.CreateConsumer(consumerDestination))
+			using(IMessageProducer producer = producerSession.CreateProducer(producerDestination))
+			{
+				producer.DeliveryMode = deliveryMode;
+
+				IMessage request = producerSession.CreateMessage();
+				request.NMSCorrelationID = "AsyncConsumeAfterSendLateListener";
+				request.NMSType = "Test";
+				producer.Send(request);
+
+				// now lets add the listener
+				consumer.Listener += new MessageListener(OnMessage);
+				WaitForMessageToArrive();
+				Assert.AreEqual(request.NMSCorrelationID, receivedMsg.NMSCorrelationID, "Invalid correlation ID.");
+			}
+		}
+
+		//[Test]
+		public virtual void TestAsynchronousTextMessageConsume(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnectionAndStart(GetTestClientId()))
+			using(ISession producerSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(ISession consumerSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(IDestination producerDestination = GetClearDestinationByNodeReference(producerSession, testDestRef))
+			using(IDestination consumerDestination = GetDestinationByNodeReference(consumerSession, testDestRef))
+			using(IMessageConsumer consumer = consumerSession.CreateConsumer(consumerDestination))
+			using(IMessageProducer producer = producerSession.CreateProducer(producerDestination))
+			{
+				consumer.Listener += new MessageListener(OnMessage);
+				producer.DeliveryMode = deliveryMode;
+
+				ITextMessage request = producerSession.CreateTextMessage("Hello, World!");
+				request.NMSCorrelationID = "AsyncConsumeTextMessage";
+				request.Properties["NMSXGroupID"] = "cheese";
+				request.Properties["myHeader"] = "James";
+
+				producer.Send(request);
+
+				WaitForMessageToArrive();
+				Assert.AreEqual(request.NMSCorrelationID, receivedMsg.NMSCorrelationID, "Invalid correlation ID.");
+				Assert.AreEqual(request.Properties["NMSXGroupID"], receivedMsg.Properties["NMSXGroupID"], "Invalid NMSXGroupID.");
+				Assert.AreEqual(request.Properties["myHeader"], receivedMsg.Properties["myHeader"], "Invalid myHeader.");
+				Assert.AreEqual(request.Text, ((ITextMessage) receivedMsg).Text, "Invalid text body.");
+			}
+		}
+
+		//[Test]
+		public virtual void TestTemporaryQueueAsynchronousConsume(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnectionAndStart(GetTestClientId()))
+			using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(ITemporaryQueue tempReplyDestination = session.CreateTemporaryQueue())
+			using(IDestination destination = GetClearDestinationByNodeReference(session, testDestRef))
+			using(IMessageConsumer consumer = session.CreateConsumer(destination))
+			using(IMessageConsumer tempConsumer = session.CreateConsumer(tempReplyDestination))
+			using(IMessageProducer producer = session.CreateProducer(destination))
+			{
+				producer.DeliveryMode = deliveryMode;
+				tempConsumer.Listener += new MessageListener(OnMessage);
+				consumer.Listener += new MessageListener(OnQueueMessage);
+
+				IMessage request = session.CreateMessage();
+				request.NMSCorrelationID = "TemqQueueAsyncConsume";
+				request.NMSType = "Test";
+				request.NMSReplyTo = tempReplyDestination;
+				producer.Send(request);
+
+				WaitForMessageToArrive();
+				Assert.AreEqual("TempQueueAsyncResponse", receivedMsg.NMSCorrelationID, "Invalid correlation ID.");
+			}
+		}
+
+		protected void OnQueueMessage(IMessage message)
+		{
+			Assert.AreEqual("TemqQueueAsyncConsume", message.NMSCorrelationID, "Invalid correlation ID.");
+			using(IConnection connection = CreateConnectionAndStart(RESPONSE_CLIENT_ID))
+			using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(IMessageProducer producer = session.CreateProducer(message.NMSReplyTo))
+			{
+				producer.DeliveryMode = message.NMSDeliveryMode;
+
+				ITextMessage response = session.CreateTextMessage("Asynchronous Response Message Text");
+				response.NMSCorrelationID = "TempQueueAsyncResponse";
+				response.NMSType = message.NMSType;
+				producer.Send(response);
+			}
+		}
+
+		protected void OnMessage(IMessage message)
+		{
+			receivedMsg = message;
+			received = true;
+			semaphore.Set();
+		}
+
+		protected void WaitForMessageToArrive()
+		{
+			semaphore.WaitOne((int) receiveTimeout.TotalMilliseconds, true);
+			Assert.IsTrue(received, "Should have received a message by now!");
+		}
+	}
+}
diff --git a/src/test/csharp/BadConsumeTest.cs b/src/test/csharp/BadConsumeTest.cs
new file mode 100644
index 0000000..76f7cfc
--- /dev/null
+++ b/src/test/csharp/BadConsumeTest.cs
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class BadConsumeTest : NMSTest
+	{
+		protected IConnection connection;
+		protected ISession session;
+
+		protected BadConsumeTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[SetUp]
+		public override void SetUp()
+		{
+			connection = CreateConnection(GetTestClientId());
+			connection.Start();
+			session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+		}
+
+		//[TearDown]
+		public override void TearDown()
+		{
+			if(null != session)
+			{
+				session.Dispose();
+				session = null;
+			}
+
+			if(null != connection)
+			{
+				connection.Dispose();
+				connection = null;
+			}
+		}
+
+		//[Test]
+		//[ExpectedException(Handler="ExceptionValidationCheck")]
+		public virtual void TestBadConsumerException()
+		{
+			session.CreateConsumer(null);
+		}
+
+		public void ExceptionValidationCheck(Exception ex)
+		{
+			Assert.IsNotNull(ex as NMSException, "Invalid exception was thrown.");
+		}
+	}
+}
diff --git a/src/test/csharp/BytesMessageTest.cs b/src/test/csharp/BytesMessageTest.cs
new file mode 100644
index 0000000..8e6468f
--- /dev/null
+++ b/src/test/csharp/BytesMessageTest.cs
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class BytesMessageTest : NMSTest
+	{
+		protected byte[] msgContent = {1, 2, 3, 4, 5, 6, 7, 8};
+
+		protected BytesMessageTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void SendReceiveBytesMessage(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						IMessage request = session.CreateBytesMessage(msgContent);
+						producer.Send(request);
+
+						IMessage message = consumer.Receive(receiveTimeout);
+                        AssertMessageIsReadOnly(message);
+						AssertBytesMessageEqual(request, message);
+						Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+					}
+				}
+			}
+		}
+
+        //[Test]
+        public virtual void SendReceiveBytesMessageContent(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+        {
+            using(IConnection connection = CreateConnection(GetTestClientId()))
+            {
+                connection.Start();
+                using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+                {
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+                    using(IMessageConsumer consumer = session.CreateConsumer(destination))
+                    using(IMessageProducer producer = session.CreateProducer(destination))
+                    {
+                        producer.DeliveryMode = deliveryMode;
+                        IBytesMessage request = session.CreateBytesMessage();
+                        
+                        request.WriteBoolean(true);
+                        request.WriteByte((byte) 1);
+                        request.WriteBytes(new byte[1]);
+                        request.WriteBytes(new byte[3], 0, 2);
+                        request.WriteChar('a');
+                        request.WriteDouble(1.5);
+                        request.WriteSingle((float) 1.5);
+                        request.WriteInt32(1);
+                        request.WriteInt64(1);
+                        request.WriteObject("stringobj");
+                        request.WriteInt16((short) 1);
+                        request.WriteString("utfstring");
+                        
+                        producer.Send(request);
+
+                        IMessage message = consumer.Receive(receiveTimeout);
+                        AssertMessageIsReadOnly(message);
+                        AssertBytesMessageEqual(request, message);
+                        Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+                    }
+                }
+            }
+        }
+        
+        protected void AssertMessageIsReadOnly(IMessage message)
+        {
+			Type writeableExceptionType = typeof(MessageNotWriteableException);
+			IBytesMessage theMessage = message as IBytesMessage;
+            Assert.IsNotNull(theMessage);
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteBoolean(true); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteByte((byte) 1); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteBytes(new byte[1]); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteBytes(new byte[3], 0, 2); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteChar('a'); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteDouble(1.5); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteSingle((float) 1.5); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteInt32(1); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteInt64(1); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteObject("stringobj"); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteInt16((short) 1); });
+			Assert.Throws(writeableExceptionType, delegate () { theMessage.WriteString("utfstring"); });
+		}
+        
+		/// <summary>
+		/// Assert that two messages are IBytesMessages and their contents are equal.
+		/// </summary>
+		/// <param name="expected"></param>
+		/// <param name="actual"></param>
+		protected void AssertBytesMessageEqual(IMessage expected, IMessage actual)
+		{
+			IBytesMessage expectedBytesMsg = expected as IBytesMessage;
+			expectedBytesMsg.Reset();
+			Assert.IsNotNull(expectedBytesMsg, "'expected' message not a bytes message");
+			IBytesMessage actualBytesMsg = actual as IBytesMessage;
+			Assert.IsNotNull(actualBytesMsg, "'actual' message not a bytes message");
+			Assert.AreEqual(expectedBytesMsg.Content, actualBytesMsg.Content, "Bytes message contents do not match.");
+		}
+	}
+}
diff --git a/src/test/csharp/Commands/BytesMessage.cs b/src/test/csharp/Commands/BytesMessage.cs
new file mode 100644
index 0000000..02fb23d
--- /dev/null
+++ b/src/test/csharp/Commands/BytesMessage.cs
@@ -0,0 +1,511 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using Apache.NMS;
+using Apache.NMS.Util;
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Apache.NMS.Commands
+{
+    public class BytesMessage : Message, IBytesMessage
+    {
+        private EndianBinaryReader dataIn = null;
+        private EndianBinaryWriter dataOut = null;
+        private MemoryStream outputBuffer = null;
+        private int length = 0;
+
+        public override Object Clone()
+        {
+            StoreContent();
+            return base.Clone();
+        }
+
+        public override void ClearBody()
+        {
+            base.ClearBody();
+            this.outputBuffer = null;
+            this.dataIn = null;
+            this.dataOut = null;
+            this.length = 0;
+        }
+
+        public long BodyLength
+        {
+            get
+            {
+                InitializeReading();
+                return this.length;
+            }
+        }
+
+        public byte ReadByte()
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.ReadByte();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteByte( byte value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public bool ReadBoolean()
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.ReadBoolean();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteBoolean( bool value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public char ReadChar()
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.ReadChar();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteChar( char value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public short ReadInt16()
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.ReadInt16();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteInt16( short value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public int ReadInt32()
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.ReadInt32();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteInt32( int value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public long ReadInt64()
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.ReadInt64();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteInt64( long value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public float ReadSingle()
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.ReadSingle();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteSingle( float value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public double ReadDouble()
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.ReadDouble();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteDouble( double value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public int ReadBytes( byte[] value )
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.Read( value, 0, value.Length );
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public int ReadBytes( byte[] value, int length )
+        {
+            InitializeReading();
+            try
+            {
+                return dataIn.Read( value, 0, length );
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteBytes( byte[] value )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value, 0, value.Length );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteBytes( byte[] value, int offset, int length )
+        {
+            InitializeWriting();
+            try
+            {
+                dataOut.Write( value, offset, length );
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public string ReadString()
+        {
+            InitializeReading();
+            try
+            {
+                // JMS, CMS and NMS all encode the String using a 16 bit size header.
+                return dataIn.ReadString16();
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteString( string value )
+        {
+            InitializeWriting();
+            try
+            {
+                // JMS, CMS and NMS all encode the String using a 16 bit size header.
+                dataOut.WriteString16(value);
+            }
+            catch(Exception e)
+            {
+                throw NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteObject( System.Object value )
+        {
+            InitializeWriting();
+            if( value is System.Byte )
+            {
+                this.dataOut.Write( (byte) value );
+            }
+            else if( value is Char )
+            {
+                this.dataOut.Write( (char) value );
+            }
+            else if( value is Boolean )
+            {
+                this.dataOut.Write( (bool) value );
+            }
+            else if( value is Int16 )
+            {
+                this.dataOut.Write( (short) value );
+            }
+            else if( value is Int32 )
+            {
+                this.dataOut.Write( (int) value );
+            }
+            else if( value is Int64 )
+            {
+                this.dataOut.Write( (long) value );
+            }
+            else if( value is Single )
+            {
+                this.dataOut.Write( (float) value );
+            }
+            else if( value is Double )
+            {
+                this.dataOut.Write( (double) value );
+            }
+            else if( value is byte[] )
+            {
+                this.dataOut.Write( (byte[]) value );
+            }
+            else if( value is String )
+            {
+                this.dataOut.WriteString16( (string) value );
+            }
+            else
+            {
+                throw new MessageFormatException("Cannot write non-primitive type:" + value.GetType());
+            }
+        }
+
+        public new byte[] Content
+        {
+            get
+            {
+                byte[] buffer = null;
+                InitializeReading();
+                if(this.length != 0)
+                {
+                    buffer = new byte[this.length];
+                    this.dataIn.Read(buffer, 0, buffer.Length);
+                }
+                return buffer;
+            }
+
+            set
+            {
+                InitializeWriting();
+                this.dataOut.Write(value, 0, value.Length);
+            }
+        }
+
+        public void Reset()
+        {
+            StoreContent();
+            this.dataIn = null;
+            this.dataOut = null;
+            this.outputBuffer = null;
+            this.ReadOnlyBody = true;
+        }
+
+        private void InitializeReading()
+        {
+            FailIfWriteOnlyBody();
+            if(this.dataIn == null)
+            {
+                byte[] data = base.Content;
+
+                if(base.Content == null)
+                {
+                    data = new byte[0];
+                }
+
+                Stream target = new MemoryStream(data, false);
+
+                this.length = data.Length;
+                this.dataIn = new EndianBinaryReader(target);
+            }
+        }
+
+        private void InitializeWriting()
+        {
+            FailIfReadOnlyBody();
+            if(this.dataOut == null)
+            {
+                this.outputBuffer = new MemoryStream();
+                this.dataOut = new EndianBinaryWriter(this.outputBuffer);
+            }
+        }
+
+        private void StoreContent()
+        {
+            if(this.dataOut != null)
+            {
+                this.dataOut.Close();
+                base.Content = outputBuffer.ToArray();
+
+                this.dataOut = null;
+                this.outputBuffer = null;
+            }
+        }
+
+    }
+}
+
diff --git a/src/test/csharp/Commands/Destination.cs b/src/test/csharp/Commands/Destination.cs
new file mode 100644
index 0000000..58c7749
--- /dev/null
+++ b/src/test/csharp/Commands/Destination.cs
@@ -0,0 +1,380 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Specialized;
+using Apache.NMS.Util;
+
+namespace Apache.NMS.Commands
+{
+    /// <summary>
+    /// Summary description for Destination.
+    /// </summary>
+    public abstract class Destination : IDestination, ICloneable
+    {
+        /// <summary>
+        /// Topic Destination object
+        /// </summary>
+        public const int TOPIC = 1;
+        /// <summary>
+        /// Temporary Topic Destination object
+        /// </summary>
+        public const int TEMPORARY_TOPIC = 2;
+        /// <summary>
+        /// Queue Destination object
+        /// </summary>
+        public const int QUEUE = 3;
+        /// <summary>
+        /// Temporary Queue Destination object
+        /// </summary>
+        public const int TEMPORARY_QUEUE = 4;
+
+        private const String TEMP_PREFIX = "{TD{";
+        private const String TEMP_POSTFIX = "}TD}";
+
+        private String physicalName = "";
+        private StringDictionary options = null;
+
+		private bool disposed = false;
+
+        /// <summary>
+        /// The Default Constructor
+        /// </summary>
+        protected Destination()
+        {
+        }
+
+        /// <summary>
+        /// Construct the Destination with a defined physical name;
+        /// </summary>
+        /// <param name="name"></param>
+        protected Destination(String name)
+        {
+            setPhysicalName(name);
+        }
+
+		~Destination()
+		{
+			Dispose(false);
+		}
+
+		public void Dispose()
+		{
+			Dispose(true);
+			GC.SuppressFinalize(this);
+		}
+
+		private void Dispose(bool disposing)
+		{
+			if(disposed)
+			{
+				return;
+			}
+
+			if(disposing)
+			{
+				try
+				{
+					OnDispose();
+				}
+				catch(Exception ex)
+				{
+					Tracer.ErrorFormat("Exception disposing Destination {0}: {1}", this.physicalName, ex.Message);
+				}
+			}
+
+			disposed = true;
+		}
+
+		/// <summary>
+		/// Child classes can override this method to perform clean-up logic.
+		/// </summary>
+		protected virtual void OnDispose()
+		{
+		}
+
+		public bool IsTopic
+        {
+            get
+            {
+                int destinationType = GetDestinationType();
+                return TOPIC == destinationType
+                    || TEMPORARY_TOPIC == destinationType;
+            }
+        }
+
+        public bool IsQueue
+        {
+            get
+            {
+                int destinationType = GetDestinationType();
+                return QUEUE == destinationType
+                    || TEMPORARY_QUEUE == destinationType;
+            }
+        }
+
+        public bool IsTemporary
+        {
+            get
+            {
+                int destinationType = GetDestinationType();
+                return TEMPORARY_QUEUE == destinationType
+                    || TEMPORARY_TOPIC == destinationType;
+            }
+        }
+
+        /// <summary>
+        /// Dictionary of name/value pairs representing option values specified
+        /// in the URI used to create this Destination.  A null value is returned
+        /// if no options were specified.
+        /// </summary>
+        internal StringDictionary Options
+        {
+            get { return this.options; }
+        }
+
+        private void setPhysicalName(string name)
+        {
+            this.physicalName = name;
+
+            int p = name.IndexOf('?');
+            if(p >= 0)
+            {
+                String optstring = physicalName.Substring(p + 1);
+                this.physicalName = name.Substring(0, p);
+                options = URISupport.ParseQuery(optstring);
+            }
+        }
+
+        /// <summary>
+        /// </summary>
+        /// <param name="destination"></param>
+        /// <returns></returns>
+        public static Destination Transform(IDestination destination)
+        {
+            Destination result = null;
+            if(destination != null)
+            {
+                if(destination is Destination)
+                {
+                    result = (Destination) destination;
+                }
+                else
+                {
+                    if(destination is ITemporaryQueue)
+                    {
+                        result = new TempQueue(((IQueue) destination).QueueName);
+                    }
+                    else if(destination is ITemporaryTopic)
+                    {
+                        result = new TempTopic(((ITopic) destination).TopicName);
+                    }
+                    else if(destination is IQueue)
+                    {
+                        result = new Queue(((IQueue) destination).QueueName);
+                    }
+                    else if(destination is ITopic)
+                    {
+                        result = new Topic(((ITopic) destination).TopicName);
+                    }
+                }
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Create a temporary name from the clientId
+        /// </summary>
+        /// <param name="clientId"></param>
+        /// <returns></returns>
+        public static String CreateTemporaryName(String clientId)
+        {
+            return TEMP_PREFIX + clientId + TEMP_POSTFIX;
+        }
+
+        /// <summary>
+        /// From a temporary destination find the clientId of the Connection that created it
+        /// </summary>
+        /// <param name="destination"></param>
+        /// <returns>the clientId or null if not a temporary destination</returns>
+        public static String GetClientId(Destination destination)
+        {
+            String answer = null;
+            if(destination != null && destination.IsTemporary)
+            {
+                String name = destination.PhysicalName;
+                int start = name.IndexOf(TEMP_PREFIX);
+                if(start >= 0)
+                {
+                    start += TEMP_PREFIX.Length;
+                    int stop = name.LastIndexOf(TEMP_POSTFIX);
+                    if(stop > start && stop < name.Length)
+                    {
+                        answer = name.Substring(start, stop);
+                    }
+                }
+            }
+            return answer;
+        }
+
+        /// <summary>
+        /// </summary>
+        /// <param name="o">object to compare</param>
+        /// <returns>1 if this is less than o else 0 if they are equal or -1 if this is less than o</returns>
+        public int CompareTo(Object o)
+        {
+            if(o is Destination)
+            {
+                return CompareTo((Destination) o);
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Lets sort by name first then lets sort topics greater than queues
+        /// </summary>
+        /// <param name="that">another destination to compare against</param>
+        /// <returns>1 if this is less than o else 0 if they are equal or -1 if this is less than o</returns>
+        public int CompareTo(Destination that)
+        {
+            int answer = 0;
+            if(physicalName != that.physicalName)
+            {
+                if(physicalName == null)
+                {
+                    return -1;
+                }
+                else if(that.physicalName == null)
+                {
+                    return 1;
+                }
+                answer = physicalName.CompareTo(that.physicalName);
+            }
+
+            if(answer == 0)
+            {
+                if(IsTopic)
+                {
+                    if(that.IsQueue)
+                    {
+                        return 1;
+                    }
+                }
+                else
+                {
+                    if(that.IsTopic)
+                    {
+                        return -1;
+                    }
+                }
+            }
+            return answer;
+        }
+
+        /// <summary>
+        /// </summary>
+        /// <returns>Returns the Destination type</returns>
+        public abstract int GetDestinationType();
+
+        public String PhysicalName
+        {
+            get { return this.physicalName; }
+            set
+            {
+                this.physicalName = value;
+            }
+        }
+
+        /// <summary>
+        /// </summary>
+        /// <returns>string representation of this instance</returns>
+        public override String ToString()
+        {
+            switch(DestinationType)
+            {
+            case DestinationType.Topic:
+            return "topic://" + PhysicalName;
+
+            case DestinationType.TemporaryTopic:
+            return "temp-topic://" + PhysicalName;
+
+            case DestinationType.TemporaryQueue:
+            return "temp-queue://" + PhysicalName;
+
+            default:
+            return "queue://" + PhysicalName;
+            }
+        }
+
+        /// <summary>
+        /// </summary>
+        /// <returns>hashCode for this instance</returns>
+        public override int GetHashCode()
+        {
+            int answer = 37;
+
+            if(this.physicalName != null)
+            {
+                answer = physicalName.GetHashCode();
+            }
+            if(IsTopic)
+            {
+                answer ^= 0xfabfab;
+            }
+            return answer;
+        }
+
+        /// <summary>
+        /// if the object passed in is equivalent, return true
+        /// </summary>
+        /// <param name="obj">the object to compare</param>
+        /// <returns>true if this instance and obj are equivalent</returns>
+        public override bool Equals(Object obj)
+        {
+            bool result = this == obj;
+            if(!result && obj != null && obj is Destination)
+            {
+                Destination other = (Destination) obj;
+                result = this.GetDestinationType() == other.GetDestinationType()
+                    && this.physicalName.Equals(other.physicalName);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Factory method to create a child destination if this destination is a composite
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns>the created Destination</returns>
+        public abstract Destination CreateDestination(String name);
+
+        public abstract DestinationType DestinationType
+        {
+            get;
+        }
+
+        public virtual Object Clone()
+        {
+            // Since we are the lowest level base class, do a
+            // shallow copy which will include the derived classes.
+            // From here we would do deep cloning of other objects
+            // if we had any.
+            return this.MemberwiseClone();
+        }
+    }
+}
+
diff --git a/src/test/csharp/Commands/MapMessage.cs b/src/test/csharp/Commands/MapMessage.cs
new file mode 100644
index 0000000..34de7aa
--- /dev/null
+++ b/src/test/csharp/Commands/MapMessage.cs
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.IO;
+using Apache.NMS;
+using Apache.NMS.Util;
+
+namespace Apache.NMS.Commands
+{
+    public class MapMessage : Message, IMapMessage
+    {
+        private PrimitiveMap body;
+        private PrimitiveMapInterceptor typeConverter;
+
+        public MapMessage() : base()
+        {
+        }
+
+        public MapMessage(PrimitiveMap body) : base()
+        {
+            this.body = body;
+            this.typeConverter = new PrimitiveMapInterceptor(this, this.body);
+        }
+
+        public override void ClearBody()
+        {
+            this.body = null;
+            this.typeConverter = null;
+            base.ClearBody();
+        }
+
+        public override bool ReadOnlyBody
+        {
+            get { return base.ReadOnlyBody; }
+
+            set
+            {
+                if(this.typeConverter != null)
+                {
+                    this.typeConverter.ReadOnly = true;
+                }
+
+                base.ReadOnlyBody = value;
+            }
+        }
+
+
+        public IPrimitiveMap Body
+        {
+            get
+            {
+                if(this.body == null)
+                {
+                    this.body = new PrimitiveMap();
+                    this.typeConverter = new PrimitiveMapInterceptor(this, this.body);
+                }
+
+                return this.typeConverter;
+            }
+
+            set
+            {
+                this.body = value as PrimitiveMap;
+                if(value != null)
+                {
+                    this.typeConverter = new PrimitiveMapInterceptor(this, value);
+                }
+                else
+                {
+                    this.typeConverter = null;
+                }
+            }
+        }
+    }
+}
diff --git a/src/test/csharp/Commands/Message.cs b/src/test/csharp/Commands/Message.cs
new file mode 100644
index 0000000..dcb38d6
--- /dev/null
+++ b/src/test/csharp/Commands/Message.cs
@@ -0,0 +1,329 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections;
+
+using Apache.NMS.Util;
+
+namespace Apache.NMS.Commands
+{
+    public class Message : IMessage, ICloneable
+    {
+        private IDestination destination;
+        private string transactionId;
+        private string messageId;
+        private string groupID;
+		private int groupSequence;
+        private string correlationId;
+        private bool persistent;
+        private long expiration;
+        private byte priority;
+        private IDestination replyTo;
+        private long timestamp;
+        private string type;
+        private bool redelivered;
+        private byte[] content;
+        private bool readOnlyMsgProperties;
+        private bool readOnlyMsgBody;
+
+        private MessagePropertyIntercepter propertyHelper;
+        private PrimitiveMap properties;
+
+        ///
+        /// <summery>
+        ///  Clone this object and return a new instance that the caller now owns.
+        /// </summery>
+        ///
+        public virtual Object Clone()
+        {
+            // Since we are the lowest level base class, do a
+            // shallow copy which will include the derived classes.
+            // From here we would do deep cloning of other objects
+            // if we had any.
+            Message o = (Message) this.MemberwiseClone();
+
+            if(this.messageId != null)
+            {
+                o.NMSMessageId = (string) this.messageId.Clone();
+            }
+			
+			return o;
+		}		
+
+        ///
+        /// <summery>
+        ///  Returns a string containing the information for this DataStructure
+        ///  such as its type and value of its elements.
+        /// </summery>
+        ///
+        public override string ToString()
+        {
+            return GetType().Name + "[" +
+                "Destination=" + destination + ", " +
+                "TransactionId=" + transactionId + ", " +
+                "MessageId=" + messageId + ", " +
+                "GroupID=" + groupID + ", " +
+                "GroupSequence=" + groupSequence + ", " +
+                "CorrelationId=" + correlationId + ", " +
+                "Expiration=" + expiration + ", " +
+                "Priority=" + priority + ", " +
+                "ReplyTo=" + replyTo + ", " +
+                "Timestamp=" + timestamp + ", " +
+                "Type=" + type + ", " +
+                "Redelivered=" + redelivered +
+                "]";
+        }
+
+        public void Acknowledge()
+        {
+        }
+		
+        public virtual void ClearBody()
+        {
+			this.content = null;
+        }
+
+        public virtual void ClearProperties()
+        {
+            this.properties.Clear();
+        }
+		
+        protected void FailIfReadOnlyBody()
+        {
+            if(ReadOnlyBody == true)
+            {
+                throw new MessageNotWriteableException("Message is in Read-Only mode.");
+            }
+        }
+
+        protected void FailIfWriteOnlyBody()
+        {
+            if(ReadOnlyBody == false)
+            {
+                throw new MessageNotReadableException("Message is in Write-Only mode.");
+            }
+        }
+		
+        #region Properties
+		
+		public string TransactionId
+		{
+			get { return this.transactionId; }
+			set { this.transactionId = value; }
+		}
+
+        public byte[] Content
+        {
+            get { return content; }
+            set { this.content = value; }
+        }
+		
+        public virtual bool ReadOnlyProperties
+        {
+            get { return this.readOnlyMsgProperties; }
+            set { this.readOnlyMsgProperties = value; }
+        }
+
+        public virtual bool ReadOnlyBody
+        {
+            get { return this.readOnlyMsgBody; }
+            set { this.readOnlyMsgBody = value; }
+        }
+		
+        public IPrimitiveMap Properties
+        {
+            get
+            {
+                if(null == properties)
+                {
+                    properties = new PrimitiveMap();
+                    propertyHelper = new MessagePropertyIntercepter(this, properties, this.ReadOnlyProperties);
+                    propertyHelper.AllowByteArrays = false;
+                }
+
+                return propertyHelper;
+            }
+        }
+
+        /// <summary>
+        /// The correlation ID used to correlate messages with conversations or long running business processes
+        /// </summary>
+        public string NMSCorrelationID
+        {
+            get { return correlationId; }
+            set { correlationId = value; }
+        }
+
+        /// <summary>
+        /// The destination of the message
+        /// </summary>
+        public IDestination NMSDestination
+        {
+            get { return destination; }
+            set { this.destination = Destination.Transform(value); }
+        }
+
+        private TimeSpan timeToLive = TimeSpan.FromMilliseconds(0);
+        /// <summary>
+        /// The time in milliseconds that this message should expire in
+        /// </summary>
+        public TimeSpan NMSTimeToLive
+        {
+            get { return timeToLive; }
+
+            set
+            {
+                timeToLive = value;
+                if(timeToLive.TotalMilliseconds > 0)
+                {
+                    long timeStamp = timestamp;
+
+                    if(timeStamp == 0)
+                    {
+                        timeStamp = DateUtils.ToJavaTimeUtc(DateTime.UtcNow);
+                    }
+
+                    expiration = timeStamp + (long) timeToLive.TotalMilliseconds;
+                }
+                else
+                {
+                    expiration = 0;
+                }
+            }
+        }
+
+        /// <summary>
+        /// The timestamp the broker added to the message
+        /// </summary>
+        public DateTime NMSTimestamp
+        {
+            get { return DateUtils.ToDateTime(timestamp); }
+            set
+            {
+                timestamp = DateUtils.ToJavaTimeUtc(value);
+                if(timeToLive.TotalMilliseconds > 0)
+                {
+                    expiration = timestamp + (long) timeToLive.TotalMilliseconds;
+                }
+            }
+        }
+
+        /// <summary>
+        /// The message ID which is set by the provider
+        /// </summary>
+        public string NMSMessageId
+        {
+            get { return this.messageId; }
+            set { this.messageId = value; }
+        }
+
+        /// <summary>
+        /// Whether or not this message is persistent
+        /// </summary>
+        public MsgDeliveryMode NMSDeliveryMode
+        {
+            get { return (persistent ? MsgDeliveryMode.Persistent : MsgDeliveryMode.NonPersistent); }
+            set { persistent = (MsgDeliveryMode.Persistent == value); }
+        }
+
+        /// <summary>
+        /// The Priority on this message
+        /// </summary>
+        public MsgPriority NMSPriority
+        {
+            get { return (MsgPriority) priority; }
+            set { priority = (byte) value; }
+        }
+
+        /// <summary>
+        /// Returns true if this message has been redelivered to this or another consumer before being acknowledged successfully.
+        /// </summary>
+        public bool NMSRedelivered
+        {
+            get { return this.redelivered; }
+            set { this.redelivered = value; }
+        }
+
+        /// <summary>
+        /// The destination that the consumer of this message should send replies to
+        /// </summary>
+        public IDestination NMSReplyTo
+        {
+            get { return replyTo; }
+            set { replyTo = Destination.Transform(value); }
+        }
+
+        /// <summary>
+        /// The type name of this message
+        /// </summary>
+        public string NMSType
+        {
+            get { return type; }
+            set { type = value; }
+        }
+
+        #endregion
+
+        #region NMS Extension headers
+
+        /// <summary>
+        /// Returns the number of times this message has been redelivered to other consumers without being acknowledged successfully.
+        /// </summary>
+        public int NMSXDeliveryCount
+        {
+            get { return 0; }
+        }
+
+        /// <summary>
+        /// The Message Group ID used to group messages together to the same consumer for the same group ID value
+        /// </summary>
+        public string NMSXGroupID
+        {
+            get { return groupID; }
+            set { groupID = value; }
+        }
+        /// <summary>
+        /// The Message Group Sequence counter to indicate the position in a group
+        /// </summary>
+        public int NMSXGroupSeq
+        {
+            get { return groupSequence; }
+            set { groupSequence = value; }
+        }
+
+        /// <summary>
+        /// Returns the ID of the producers transaction
+        /// </summary>
+        public string NMSXProducerTXID
+        {
+            get
+            {
+                if(null != transactionId)
+                {
+                    return transactionId;
+                }
+
+                return String.Empty;
+            }
+        }
+
+        #endregion
+
+    };
+}
+
diff --git a/src/test/csharp/Commands/ObjectMessage.cs b/src/test/csharp/Commands/ObjectMessage.cs
new file mode 100644
index 0000000..4db9de6
--- /dev/null
+++ b/src/test/csharp/Commands/ObjectMessage.cs
@@ -0,0 +1,44 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.Collections;
+using System.IO;
+
+using Apache.NMS;
+
+namespace Apache.NMS.Commands
+{
+    public class ObjectMessage : Message, IObjectMessage
+    {
+        private object body;
+
+        public override string ToString() {
+            return GetType().Name + "["
+                + " ]";
+        }
+
+        // Properties
+
+        public object Body
+        {
+            get { return body; }
+            set { body = value; }
+        }
+
+    }
+}
diff --git a/src/test/csharp/Commands/Queue.cs b/src/test/csharp/Commands/Queue.cs
new file mode 100644
index 0000000..342156f
--- /dev/null
+++ b/src/test/csharp/Commands/Queue.cs
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Commands
+{
+    /// <summary>
+    /// Summary description for Queue.
+    /// </summary>
+    public class Queue : Destination, IQueue
+    {
+        public Queue()
+            : base()
+        {
+        }
+
+        public Queue(String name)
+            : base(name)
+        {
+        }
+
+        override public DestinationType DestinationType
+        {
+            get
+            {
+                return DestinationType.Queue;
+            }
+        }
+
+        public String QueueName
+        {
+            get { return PhysicalName; }
+        }
+
+        public override int GetDestinationType()
+        {
+            return QUEUE;
+        }
+
+        public override Destination CreateDestination(String name)
+        {
+            return new Queue(name);
+        }
+
+        public override Object Clone()
+        {
+            // Since we are a derived class use the base's Clone()
+            // to perform the shallow copy. Since it is shallow it
+            // will include our derived class. Since we are derived,
+            // this method is an override.
+            Queue o = (Queue) base.Clone();
+
+            // Now do the deep work required
+            // If any new variables are added then this routine will
+            // likely need updating
+
+            return o;
+        }
+    }
+}
+
diff --git a/src/test/csharp/Commands/StreamMessage.cs b/src/test/csharp/Commands/StreamMessage.cs
new file mode 100644
index 0000000..86e4e28
--- /dev/null
+++ b/src/test/csharp/Commands/StreamMessage.cs
@@ -0,0 +1,901 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.IO;
+using System.Collections;
+
+using Apache.NMS;
+using Apache.NMS.Util;
+
+namespace Apache.NMS.Commands
+{
+    public class StreamMessage : Message, IStreamMessage
+    {
+        private EndianBinaryReader dataIn = null;
+        private EndianBinaryWriter dataOut = null;
+        private MemoryStream byteBuffer = null;
+        private int bytesRemaining = -1;
+
+        public bool ReadBoolean()
+        {
+            InitializeReading();
+
+            try
+            {
+                long startingPos = this.byteBuffer.Position;
+                try
+                {
+                    int type = this.dataIn.ReadByte();
+
+                    if(type == PrimitiveMap.BOOLEAN_TYPE)
+                    {
+                        return this.dataIn.ReadBoolean();
+                    }
+                    else if(type == PrimitiveMap.STRING_TYPE)
+                    {
+                        return Boolean.Parse(this.dataIn.ReadString16());
+                    }
+                    else if(type == PrimitiveMap.NULL)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new NMSException("Cannot convert Null type to a bool");
+                    }
+                    else
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Value is not a Boolean type.");
+                    }
+                }
+                catch(FormatException e)
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw NMSExceptionSupport.CreateMessageFormatException(e);
+                }
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public byte ReadByte()
+        {
+            InitializeReading();
+
+            try
+            {
+                long startingPos = this.byteBuffer.Position;
+                try
+                {
+                    int type = this.dataIn.ReadByte();
+
+                    if(type == PrimitiveMap.BYTE_TYPE)
+                    {
+                        return this.dataIn.ReadByte();
+                    }
+                    else if(type == PrimitiveMap.STRING_TYPE)
+                    {
+                        return Byte.Parse(this.dataIn.ReadString16());
+                    }
+                    else if(type == PrimitiveMap.NULL)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new NMSException("Cannot convert Null type to a byte");
+                    }
+                    else
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Value is not a Byte type.");
+                    }
+                }
+                catch(FormatException e)
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw NMSExceptionSupport.CreateMessageFormatException(e);
+                }
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public char ReadChar()
+        {
+            InitializeReading();
+
+            try
+            {
+                long startingPos = this.byteBuffer.Position;
+                try
+                {
+                    int type = this.dataIn.ReadByte();
+
+                    if(type == PrimitiveMap.CHAR_TYPE)
+                    {
+                        return this.dataIn.ReadChar();
+                    }
+                    else if(type == PrimitiveMap.NULL)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new NMSException("Cannot convert Null type to a char");
+                    }
+                    else
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Value is not a Char type.");
+                    }
+                }
+                catch(FormatException e)
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw NMSExceptionSupport.CreateMessageFormatException(e);
+                }
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public short ReadInt16()
+        {
+            InitializeReading();
+
+            try
+            {
+                long startingPos = this.byteBuffer.Position;
+                try
+                {
+                    int type = this.dataIn.ReadByte();
+
+                    if(type == PrimitiveMap.SHORT_TYPE)
+                    {
+                        return this.dataIn.ReadInt16();
+                    }
+                    else if(type == PrimitiveMap.BYTE_TYPE)
+                    {
+                        return this.dataIn.ReadByte();
+                    }
+                    else if(type == PrimitiveMap.STRING_TYPE)
+                    {
+                        return Int16.Parse(this.dataIn.ReadString16());
+                    }
+                    else if(type == PrimitiveMap.NULL)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new NMSException("Cannot convert Null type to a short");
+                    }
+                    else
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Value is not a Int16 type.");
+                    }
+                }
+                catch(FormatException e)
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw NMSExceptionSupport.CreateMessageFormatException(e);
+                }
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public int ReadInt32()
+        {
+            InitializeReading();
+
+            try
+            {
+                long startingPos = this.byteBuffer.Position;
+                try
+                {
+                    int type = this.dataIn.ReadByte();
+
+                    if(type == PrimitiveMap.INTEGER_TYPE)
+                    {
+                        return this.dataIn.ReadInt32();
+                    }
+                    else if(type == PrimitiveMap.SHORT_TYPE)
+                    {
+                        return this.dataIn.ReadInt16();
+                    }
+                    else if(type == PrimitiveMap.BYTE_TYPE)
+                    {
+                        return this.dataIn.ReadByte();
+                    }
+                    else if(type == PrimitiveMap.STRING_TYPE)
+                    {
+                        return Int32.Parse(this.dataIn.ReadString16());
+                    }
+                    else if(type == PrimitiveMap.NULL)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new NMSException("Cannot convert Null type to a int");
+                    }
+                    else
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Value is not a Int32 type.");
+                    }
+                }
+                catch(FormatException e)
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw NMSExceptionSupport.CreateMessageFormatException(e);
+                }
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public long ReadInt64()
+        {
+            InitializeReading();
+
+            try
+            {
+                long startingPos = this.byteBuffer.Position;
+                try
+                {
+                    int type = this.dataIn.ReadByte();
+
+                    if(type == PrimitiveMap.LONG_TYPE)
+                    {
+                        return this.dataIn.ReadInt64();
+                    }
+                    else if(type == PrimitiveMap.INTEGER_TYPE)
+                    {
+                        return this.dataIn.ReadInt32();
+                    }
+                    else if(type == PrimitiveMap.SHORT_TYPE)
+                    {
+                        return this.dataIn.ReadInt16();
+                    }
+                    else if(type == PrimitiveMap.BYTE_TYPE)
+                    {
+                        return this.dataIn.ReadByte();
+                    }
+                    else if(type == PrimitiveMap.STRING_TYPE)
+                    {
+                        return Int64.Parse(this.dataIn.ReadString16());
+                    }
+                    else if(type == PrimitiveMap.NULL)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new NMSException("Cannot convert Null type to a long");
+                    }
+                    else
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Value is not a Int64 type.");
+                    }
+                }
+                catch(FormatException e)
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw NMSExceptionSupport.CreateMessageFormatException(e);
+                }
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public float ReadSingle()
+        {
+            InitializeReading();
+
+            try
+            {
+                long startingPos = this.byteBuffer.Position;
+                try
+                {
+                    int type = this.dataIn.ReadByte();
+
+                    if(type == PrimitiveMap.FLOAT_TYPE)
+                    {
+                        return this.dataIn.ReadSingle();
+                    }
+                    else if(type == PrimitiveMap.STRING_TYPE)
+                    {
+                        return Single.Parse(this.dataIn.ReadString16());
+                    }
+                    else if(type == PrimitiveMap.NULL)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new NMSException("Cannot convert Null type to a float");
+                    }
+                    else
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Value is not a Single type.");
+                    }
+                }
+                catch(FormatException e)
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw NMSExceptionSupport.CreateMessageFormatException(e);
+                }
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public double ReadDouble()
+        {
+            InitializeReading();
+
+            try
+            {
+                long startingPos = this.byteBuffer.Position;
+                try
+                {
+                    int type = this.dataIn.ReadByte();
+
+                    if(type == PrimitiveMap.DOUBLE_TYPE)
+                    {
+                        return this.dataIn.ReadDouble();
+                    }
+                    else if(type == PrimitiveMap.FLOAT_TYPE)
+                    {
+                        return this.dataIn.ReadSingle();
+                    }
+                    else if(type == PrimitiveMap.STRING_TYPE)
+                    {
+                        return Single.Parse(this.dataIn.ReadString16());
+                    }
+                    else if(type == PrimitiveMap.NULL)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new NMSException("Cannot convert Null type to a double");
+                    }
+                    else
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Value is not a Double type.");
+                    }
+                }
+                catch(FormatException e)
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw NMSExceptionSupport.CreateMessageFormatException(e);
+                }
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public string ReadString()
+        {
+            InitializeReading();
+
+            long startingPos = this.byteBuffer.Position;
+
+            try
+            {
+                int type = this.dataIn.ReadByte();
+
+                if(type == PrimitiveMap.BIG_STRING_TYPE)
+                {
+                    return this.dataIn.ReadString32();
+                }
+                else if(type == PrimitiveMap.STRING_TYPE)
+                {
+                    return this.dataIn.ReadString16();
+                }
+                else if(type == PrimitiveMap.LONG_TYPE)
+                {
+                    return this.dataIn.ReadInt64().ToString();
+                }
+                else if(type == PrimitiveMap.INTEGER_TYPE)
+                {
+                    return this.dataIn.ReadInt32().ToString();
+                }
+                else if(type == PrimitiveMap.SHORT_TYPE)
+                {
+                    return this.dataIn.ReadInt16().ToString();
+                }
+                else if(type == PrimitiveMap.FLOAT_TYPE)
+                {
+                    return this.dataIn.ReadSingle().ToString();
+                }
+                else if(type == PrimitiveMap.DOUBLE_TYPE)
+                {
+                    return this.dataIn.ReadDouble().ToString();
+                }
+                else if(type == PrimitiveMap.CHAR_TYPE)
+                {
+                    return this.dataIn.ReadChar().ToString();
+                }
+                else if(type == PrimitiveMap.BYTE_TYPE)
+                {
+                    return this.dataIn.ReadByte().ToString();
+                }
+                else if(type == PrimitiveMap.BOOLEAN_TYPE)
+                {
+                    return this.dataIn.ReadBoolean().ToString();
+                }
+                else if(type == PrimitiveMap.NULL)
+                {
+                    return null;
+                }
+                else
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw new MessageFormatException("Value is not a known type.");
+                }
+            }
+            catch(FormatException e)
+            {
+                this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public int ReadBytes(byte[] value)
+        {
+            InitializeReading();
+
+            if(value == null)
+            {
+                throw new NullReferenceException("Passed Byte Array is null");
+            }
+
+            try
+            {
+                if(this.bytesRemaining == -1)
+                {
+                    long startingPos = this.byteBuffer.Position;
+                    byte type = this.dataIn.ReadByte();
+
+                    if(type != PrimitiveMap.BYTE_ARRAY_TYPE)
+                    {
+                        this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                        throw new MessageFormatException("Not a byte array");
+                    }
+
+                    this.bytesRemaining = this.dataIn.ReadInt32();
+                }
+                else if(this.bytesRemaining == 0)
+                {
+                    this.bytesRemaining = -1;
+                    return -1;
+                }
+
+                if(value.Length <= this.bytesRemaining)
+                {
+                    // small buffer
+                    this.bytesRemaining -= value.Length;
+                    this.dataIn.Read(value, 0, value.Length);
+                    return value.Length;
+                }
+                else
+                {
+                    // big buffer
+                    int rc = this.dataIn.Read(value, 0, this.bytesRemaining);
+                    this.bytesRemaining = 0;
+                    return rc;
+                }
+            }
+            catch(EndOfStreamException ex)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(ex);
+            }
+            catch(IOException ex)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(ex);
+            }
+        }
+
+        public Object ReadObject()
+        {
+            InitializeReading();
+
+            long startingPos = this.byteBuffer.Position;
+
+            try
+            {
+                int type = this.dataIn.ReadByte();
+
+                if(type == PrimitiveMap.BIG_STRING_TYPE)
+                {
+                    return this.dataIn.ReadString32();
+                }
+                else if(type == PrimitiveMap.STRING_TYPE)
+                {
+                    return this.dataIn.ReadString16();
+                }
+                else if(type == PrimitiveMap.LONG_TYPE)
+                {
+                    return this.dataIn.ReadInt64();
+                }
+                else if(type == PrimitiveMap.INTEGER_TYPE)
+                {
+                    return this.dataIn.ReadInt32();
+                }
+                else if(type == PrimitiveMap.SHORT_TYPE)
+                {
+                    return this.dataIn.ReadInt16();
+                }
+                else if(type == PrimitiveMap.FLOAT_TYPE)
+                {
+                    return this.dataIn.ReadSingle();
+                }
+                else if(type == PrimitiveMap.DOUBLE_TYPE)
+                {
+                    return this.dataIn.ReadDouble();
+                }
+                else if(type == PrimitiveMap.CHAR_TYPE)
+                {
+                    return this.dataIn.ReadChar();
+                }
+                else if(type == PrimitiveMap.BYTE_TYPE)
+                {
+                    return this.dataIn.ReadByte();
+                }
+                else if(type == PrimitiveMap.BOOLEAN_TYPE)
+                {
+                    return this.dataIn.ReadBoolean();
+                }
+                else if(type == PrimitiveMap.BYTE_ARRAY_TYPE)
+                {
+                    int length = this.dataIn.ReadInt32();
+                    byte[] data = new byte[length];
+                    this.dataIn.Read(data, 0, length);
+                    return data;
+                }
+                else if(type == PrimitiveMap.NULL)
+                {
+                    return null;
+                }
+                else
+                {
+                    this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                    throw new MessageFormatException("Value is not a known type.");
+                }
+            }
+            catch(FormatException e)
+            {
+                this.byteBuffer.Seek(startingPos, SeekOrigin.Begin);
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+            catch(EndOfStreamException e)
+            {
+                throw NMSExceptionSupport.CreateMessageEOFException(e);
+            }
+            catch(IOException e)
+            {
+                throw NMSExceptionSupport.CreateMessageFormatException(e);
+            }
+        }
+
+        public void WriteBoolean(bool value)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.BOOLEAN_TYPE);
+                this.dataOut.Write(value);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteByte(byte value)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.BYTE_TYPE);
+                this.dataOut.Write(value);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteBytes(byte[] value)
+        {
+            InitializeWriting();
+            this.WriteBytes(value, 0, value.Length);
+        }
+
+        public void WriteBytes(byte[] value, int offset, int length)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.BYTE_ARRAY_TYPE);
+                this.dataOut.Write((int) length);
+                this.dataOut.Write(value, offset, length);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteChar(char value)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.CHAR_TYPE);
+                this.dataOut.Write(value);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteInt16(short value)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.SHORT_TYPE);
+                this.dataOut.Write(value);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteInt32(int value)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.INTEGER_TYPE);
+                this.dataOut.Write(value);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteInt64(long value)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.LONG_TYPE);
+                this.dataOut.Write(value);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteSingle(float value)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.FLOAT_TYPE);
+                this.dataOut.Write(value);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteDouble(double value)
+        {
+            InitializeWriting();
+            try
+            {
+                this.dataOut.Write(PrimitiveMap.DOUBLE_TYPE);
+                this.dataOut.Write(value);
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteString(string value)
+        {
+            InitializeWriting();
+            try
+            {
+                if( value.Length > 8192 )
+                {
+                    this.dataOut.Write(PrimitiveMap.BIG_STRING_TYPE);
+                    this.dataOut.WriteString32(value);
+                }
+                else
+                {
+                    this.dataOut.Write(PrimitiveMap.STRING_TYPE);
+                    this.dataOut.WriteString16(value);
+                }
+            }
+            catch(IOException e)
+            {
+                NMSExceptionSupport.Create(e);
+            }
+        }
+
+        public void WriteObject(Object value)
+        {
+            InitializeWriting();
+            if( value is System.Byte )
+            {
+                this.WriteByte( (byte) value );
+            }
+            else if( value is Char )
+            {
+                this.WriteChar( (char) value );
+            }
+            else if( value is Boolean )
+            {
+                this.WriteBoolean( (bool) value );
+            }
+            else if( value is Int16 )
+            {
+                this.WriteInt16( (short) value );
+            }
+            else if( value is Int32 )
+            {
+                this.WriteInt32( (int) value );
+            }
+            else if( value is Int64 )
+            {
+                this.WriteInt64( (long) value );
+            }
+            else if( value is Single )
+            {
+                this.WriteSingle( (float) value );
+            }
+            else if( value is Double )
+            {
+                this.WriteDouble( (double) value );
+            }
+            else if( value is byte[] )
+            {
+                this.WriteBytes( (byte[]) value );
+            }
+            else if( value is String )
+            {
+                this.WriteString( (string) value );
+            }
+            else
+            {
+                throw new MessageFormatException("Cannot write non-primitive type:" + value.GetType());
+            }
+        }
+
+        public override Object Clone()
+        {
+            StoreContent();
+            return base.Clone();
+        }
+
+        public override void ClearBody()
+        {
+            base.ClearBody();
+            this.byteBuffer = null;
+            this.dataIn = null;
+            this.dataOut = null;
+            this.bytesRemaining = -1;
+        }
+
+        public void Reset()
+        {
+            StoreContent();
+            this.dataIn = null;
+            this.dataOut = null;
+            this.byteBuffer = null;
+            this.bytesRemaining = -1;
+            this.ReadOnlyBody = true;
+        }
+
+        private void InitializeReading()
+        {
+            FailIfWriteOnlyBody();
+            if(this.dataIn == null)
+            {
+                this.byteBuffer = new MemoryStream(this.Content, false);
+                this.dataIn = new EndianBinaryReader(this.byteBuffer);
+            }
+        }
+
+        private void InitializeWriting()
+        {
+            FailIfReadOnlyBody();
+            if(this.dataOut == null)
+            {
+                this.byteBuffer = new MemoryStream();
+                this.dataOut = new EndianBinaryWriter(this.byteBuffer);
+            }
+        }
+
+        private void StoreContent()
+        {
+            if( dataOut != null)
+            {
+                dataOut.Close();
+
+                this.Content = byteBuffer.ToArray();
+                this.dataOut = null;
+                this.byteBuffer = null;
+            }
+        }
+
+    }
+}
+
diff --git a/src/test/csharp/Commands/TempDestination.cs b/src/test/csharp/Commands/TempDestination.cs
new file mode 100644
index 0000000..1e085c9
--- /dev/null
+++ b/src/test/csharp/Commands/TempDestination.cs
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Apache.NMS.Commands
+{
+    public abstract class TempDestination : Destination
+    {
+        /// <summary>
+        /// Method CreateDestination
+        /// </summary>
+        /// <returns>An Destination</returns>
+        /// <param name="name">A  String</param>
+        public override Destination CreateDestination(String name)
+        {
+            return null;
+        }
+
+        abstract override public DestinationType DestinationType
+        {
+            get;
+        }
+
+        public TempDestination()
+            : base()
+        {
+        }
+
+        public TempDestination(String name)
+            : base(name)
+        {
+        }
+
+        public override Object Clone()
+        {
+            // Since we are a derived class use the base's Clone()
+            // to perform the shallow copy. Since it is shallow it
+            // will include our derived class. Since we are derived,
+            // this method is an override.
+            TempDestination o = (TempDestination) base.Clone();
+
+            // Now do the deep work required
+            // If any new variables are added then this routine will
+            // likely need updating
+
+            return o;
+        }
+
+        public void Delete()
+        {
+            throw new NotSupportedException("Stomp Cannot Delete Temporary Destinations");
+        }
+    }
+}
+
diff --git a/src/test/csharp/Commands/TempQueue.cs b/src/test/csharp/Commands/TempQueue.cs
new file mode 100644
index 0000000..b8ee277
--- /dev/null
+++ b/src/test/csharp/Commands/TempQueue.cs
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Commands
+{
+    /// <summary>
+    /// A Temporary Queue
+    /// </summary>
+    public class TempQueue : TempDestination, ITemporaryQueue
+    {
+        public TempQueue()
+            : base()
+        {
+        }
+
+        public TempQueue(String name)
+            : base(name)
+        {
+        }
+
+        override public DestinationType DestinationType
+        {
+            get
+            {
+                return DestinationType.TemporaryQueue;
+            }
+        }
+
+        public String QueueName
+        {
+            get { return PhysicalName; }
+        }
+
+        public String GetQueueName()
+        {
+            return PhysicalName;
+        }
+
+        public override int GetDestinationType()
+        {
+            return TEMPORARY_QUEUE;
+        }
+
+        public override Destination CreateDestination(String name)
+        {
+            return new TempQueue(name);
+        }
+
+        public override Object Clone()
+        {
+            // Since we are a derived class use the base's Clone()
+            // to perform the shallow copy. Since it is shallow it
+            // will include our derived class. Since we are derived,
+            // this method is an override.
+            TempQueue o = (TempQueue) base.Clone();
+
+            // Now do the deep work required
+            // If any new variables are added then this routine will
+            // likely need updating
+
+            return o;
+        }
+
+    }
+}
+
diff --git a/src/test/csharp/Commands/TempTopic.cs b/src/test/csharp/Commands/TempTopic.cs
new file mode 100644
index 0000000..2ba499e
--- /dev/null
+++ b/src/test/csharp/Commands/TempTopic.cs
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Commands
+{
+
+    /// <summary>
+    /// A Temporary Topic
+    /// </summary>
+    public class TempTopic : TempDestination, ITemporaryTopic
+    {
+        public TempTopic() : base()
+        {
+        }
+
+        public TempTopic(String name) : base(name)
+        {
+        }
+
+        override public DestinationType DestinationType
+        {
+            get { return DestinationType.TemporaryTopic; }
+        }
+
+        public String TopicName
+        {
+            get { return PhysicalName; }
+        }
+
+        public String GetTopicName()
+        {
+            return PhysicalName;
+        }
+
+        public override int GetDestinationType()
+        {
+            return TEMPORARY_TOPIC;
+        }
+
+        public override Destination CreateDestination(String name)
+        {
+            return new TempTopic(name);
+        }
+
+        public override Object Clone()
+        {
+            // Since we are a derived class use the base's Clone()
+            // to perform the shallow copy. Since it is shallow it
+            // will include our derived class. Since we are derived,
+            // this method is an override.
+            TempTopic o = (TempTopic) base.Clone();
+
+            // Now do the deep work required
+            // If any new variables are added then this routine will
+            // likely need updating
+
+            return o;
+        }
+
+    }
+}
+
diff --git a/src/test/csharp/Commands/TextMessage.cs b/src/test/csharp/Commands/TextMessage.cs
new file mode 100644
index 0000000..b36f4ba
--- /dev/null
+++ b/src/test/csharp/Commands/TextMessage.cs
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.IO;
+
+using Apache.NMS;
+using Apache.NMS.Util;
+
+namespace Apache.NMS.Commands
+{
+    public class TextMessage : Message, ITextMessage
+    {
+        private String text = null;
+
+        public TextMessage()
+        {
+        }
+
+        public TextMessage(String text)
+        {
+            this.Text = text;
+        }
+
+        public override string ToString()
+        {
+            string text = this.Text;
+
+            if(text != null && text.Length > 63)
+            {
+                text = text.Substring(0, 45) + "..." + text.Substring(text.Length - 12);
+            }
+            return base.ToString() + " Text = " + (text ?? "null");
+        }
+
+        public override void ClearBody()
+        {
+            base.ClearBody();
+            this.text = null;
+        }
+
+        // Properties
+
+        public string Text
+        {
+            get { return this.text; }
+            set
+            {
+                FailIfReadOnlyBody();
+                this.text = value;
+                this.Content = null;
+            }
+        }
+    }
+}
+
diff --git a/src/test/csharp/Commands/Topic.cs b/src/test/csharp/Commands/Topic.cs
new file mode 100644
index 0000000..bbab902
--- /dev/null
+++ b/src/test/csharp/Commands/Topic.cs
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Apache.NMS.Commands
+{
+
+    /// <summary>
+    /// Summary description for Topic.
+    /// </summary>
+    public class Topic : Destination, ITopic
+    {
+        public Topic() : base()
+        {
+        }
+
+        public Topic(String name) : base(name)
+        {
+        }
+
+        override public DestinationType DestinationType
+        {
+            get
+            {
+                return DestinationType.Topic;
+            }
+        }
+
+        public String TopicName
+        {
+            get { return PhysicalName; }
+        }
+
+        public override int GetDestinationType()
+        {
+            return TOPIC;
+        }
+
+        public override Destination CreateDestination(String name)
+        {
+            return new Topic(name);
+        }
+
+        public override Object Clone()
+        {
+            // Since we are a derived class use the base's Clone()
+            // to perform the shallow copy. Since it is shallow it
+            // will include our derived class. Since we are derived,
+            // this method is an override.
+            Topic o = (Topic) base.Clone();
+
+            // Now do the deep work required
+            // If any new variables are added then this routine will
+            // likely need updating
+
+            return o;
+        }
+    }
+}
+
diff --git a/src/test/csharp/ConnectionTest.cs b/src/test/csharp/ConnectionTest.cs
new file mode 100644
index 0000000..0718f83
--- /dev/null
+++ b/src/test/csharp/ConnectionTest.cs
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class ConnectionTest : NMSTest
+	{
+		IConnection startedConnection = null;
+		IConnection stoppedConnection = null;
+
+		protected ConnectionTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[SetUp]
+		public override void SetUp()
+		{
+			base.SetUp();
+
+			startedConnection = CreateConnection(null);
+			startedConnection.Start();
+			stoppedConnection = CreateConnection(null);
+		}
+
+		//[TearDown]
+		public override void TearDown()
+		{
+			startedConnection.Close();
+			stoppedConnection.Close();
+
+			base.TearDown();
+		}
+
+		/// <summary>
+		/// Verify that it is possible to create multiple connections to the broker.
+		/// There was a bug in the connection factory which set the clientId member which made
+		/// it impossible to create an additional connection.
+		/// </summary>
+		//[Test]
+		public virtual void TestTwoConnections()
+		{
+			using(IConnection connection1 = CreateConnection(null))
+			{
+				connection1.Start();
+				using(IConnection connection2 = CreateConnection(null))
+				{
+					// with the bug present we'll get an exception in connection2.start()
+					connection2.Start();
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestCreateAndDisposeWithConsumer(
+			//[Values(true, false)]
+			bool disposeConsumer, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection("DisposalTestConnection"))
+			{
+				connection.Start();
+
+				using(ISession session = connection.CreateSession())
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					IMessageConsumer consumer = session.CreateConsumer(destination);
+
+					connection.Stop();
+					if(disposeConsumer)
+					{
+						consumer.Dispose();
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestCreateAndDisposeWithProducer(
+			//[Values(true, false)]
+			bool disposeProducer, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection("DisposalTestConnection"))
+			{
+				connection.Start();
+
+				using(ISession session = connection.CreateSession())
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					IMessageProducer producer = session.CreateProducer(destination);
+
+					connection.Stop();
+					if(disposeProducer)
+					{
+						producer.Dispose();
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestStartAfterSend(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode,
+			string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+
+				// Send the messages
+				SendMessages(session, destination, deliveryMode, 1);
+
+				// Start the conncection after the message was sent.
+				connection.Start();
+
+				// Make sure only 1 message was delivered.
+				Assert.IsNotNull(consumer.Receive(TimeSpan.FromMilliseconds(1000)));
+				Assert.IsNull(consumer.ReceiveNoWait());
+			}
+		}
+
+		/// <summary>
+		/// Tests if the consumer receives the messages that were sent before the
+		/// connection was started.
+		/// </summary>
+		//[Test]
+		public virtual void TestStoppedConsumerHoldsMessagesTillStarted(string testDestRef)
+		{
+			ISession startedSession = startedConnection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+			ISession stoppedSession = stoppedConnection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+
+			// Setup the consumers.
+			IDestination destination = GetClearDestinationByNodeReference(startedSession, testDestRef);
+			IMessageConsumer startedConsumer = startedSession.CreateConsumer(destination);
+			IMessageConsumer stoppedConsumer = stoppedSession.CreateConsumer(destination);
+
+			// Send the message.
+			IMessageProducer producer = startedSession.CreateProducer(destination);
+			ITextMessage message = startedSession.CreateTextMessage("Hello");
+			producer.Send(message);
+
+			// Test the assertions.
+			IMessage m;
+            if(destination.IsTopic)
+            {
+                m = startedConsumer.Receive(TimeSpan.FromMilliseconds(1000));
+			    Assert.IsNotNull(m);
+            }
+
+			m = stoppedConsumer.Receive(TimeSpan.FromMilliseconds(1000));
+			Assert.IsNull(m);
+
+			stoppedConnection.Start();
+			m = stoppedConsumer.Receive(TimeSpan.FromMilliseconds(5000));
+			Assert.IsNotNull(m);
+
+			startedSession.Close();
+			stoppedSession.Close();
+		}
+
+		/// <summary>
+		/// Tests if the consumer is able to receive messages even when the
+		/// connecction restarts multiple times.
+		/// </summary>
+		//[Test]
+		public virtual void TestMultipleConnectionStops(string testDestRef)
+		{
+			TestStoppedConsumerHoldsMessagesTillStarted(testDestRef);
+			stoppedConnection.Stop();
+			TestStoppedConsumerHoldsMessagesTillStarted(testDestRef);
+			stoppedConnection.Stop();
+			TestStoppedConsumerHoldsMessagesTillStarted(testDestRef);
+		}
+	}
+}
diff --git a/src/test/csharp/ConsumerTest.cs b/src/test/csharp/ConsumerTest.cs
new file mode 100644
index 0000000..ebe761a
--- /dev/null
+++ b/src/test/csharp/ConsumerTest.cs
@@ -0,0 +1,596 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Threading;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class ConsumerTest : NMSTest
+	{
+		protected const int COUNT = 25;
+		protected const string VALUE_NAME = "value";
+
+		private bool dontAck;
+
+		protected ConsumerTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+// The .NET CF does not have the ability to interrupt threads, so this test is impossible.
+#if !NETCF
+		//[Test]
+		public virtual void TestNoTimeoutConsumer(
+            string testDestRef,
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+			//	AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			// Launch a thread to perform IMessageConsumer.Receive().
+			// If it doesn't fail in less than three seconds, no exception was thrown.
+			Thread receiveThread = new Thread(new ThreadStart(TimeoutConsumerThreadProc));
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(ackMode))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(this.timeoutConsumer = session.CreateConsumer(destination))
+					{
+						receiveThread.Start();
+						if(receiveThread.Join(3000))
+						{
+							Assert.Fail("IMessageConsumer.Receive() returned without blocking.  Test failed.");
+						}
+						else
+						{
+                            try
+                            {
+							    // Kill the thread - otherwise it'll sit in Receive() until a message arrives.
+							    receiveThread.Interrupt();
+                                // MSMQ MessageQueue.Receive is interrupted neither by Thread.Interrupt, nor by
+                                // Thread.Abort. Send a dummy message to stop the background thread.
+                                IMessageProducer producer = session.CreateProducer(destination);
+                                producer.Send(session.CreateMessage());
+                            }
+                            catch
+                            {
+                            }
+						}
+					}
+				}
+			}
+		}
+
+		protected IMessageConsumer timeoutConsumer;
+
+		protected void TimeoutConsumerThreadProc()
+		{
+			try
+			{
+				timeoutConsumer.Receive();
+			}
+			catch(ArgumentOutOfRangeException e)
+			{
+				// The test failed.  We will know because the timeout will expire inside TestNoTimeoutConsumer().
+				Assert.Fail("Test failed with exception: " + e.Message);
+			}
+			catch(ThreadInterruptedException)
+			{
+				// The test succeeded!  We were still blocked when we were interrupted.
+			}
+			catch(Exception e)
+			{
+				// Some other exception occurred.
+				Assert.Fail("Test failed with exception: " + e.Message);
+			}
+		}
+
+		//[Test]
+		public virtual void TestSyncReceiveConsumerClose(
+            string testDestRef,
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+			//	AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			// Launch a thread to perform IMessageConsumer.Receive().
+			// If it doesn't fail in less than three seconds, no exception was thrown.
+			Thread receiveThread = new Thread(new ThreadStart(TimeoutConsumerThreadProc));
+			using (IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using (ISession session = connection.CreateSession(ackMode))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using (this.timeoutConsumer = session.CreateConsumer(destination))
+					{
+						receiveThread.Start();
+						if (receiveThread.Join(3000))
+						{
+							Assert.Fail("IMessageConsumer.Receive() returned without blocking.  Test failed.");
+						}
+						else
+						{
+							// Kill the thread - otherwise it'll sit in Receive() until a message arrives.
+							this.timeoutConsumer.Close();
+							receiveThread.Join(10000);
+							if (receiveThread.IsAlive)
+							{
+								Assert.Fail("IMessageConsumer.Receive() thread is still alive, Close should have killed it.");
+                                try
+                                {
+							        // Kill the thread - otherwise it'll sit in Receive() until a message arrives.
+							        receiveThread.Interrupt();
+                                    // MSMQ MessageQueue.Receive is interrupted neither by Thread.Interrupt, nor by
+                                    // Thread.Abort. Send a dummy message to stop the background thread.
+                                    IMessageProducer producer = session.CreateProducer(destination);
+                                    producer.Send(session.CreateMessage());
+                                }
+                                catch
+                                {
+                                }
+							}
+						}
+					}
+				}
+			}
+		}
+
+		internal class ThreadArg
+		{
+			internal IConnection connection = null;
+			internal ISession session = null;
+			internal IDestination destination = null;
+		}
+
+		protected void DelayedProducerThreadProc(Object arg)
+		{
+			try
+			{
+				ThreadArg args = arg as ThreadArg;
+
+				using(ISession session = args.connection.CreateSession())
+				{
+					using(IMessageProducer producer = session.CreateProducer(args.destination))
+					{
+						// Give the consumer time to enter the receive.
+						Thread.Sleep(5000);
+
+						producer.Send(args.session.CreateTextMessage("Hello World"));
+					}
+				}
+			}
+			catch(Exception e)
+			{
+				// Some other exception occurred.
+				Assert.Fail("Test failed with exception: " + e.Message);
+			}
+		}
+
+		//[Test]
+		public virtual void TestDoChangeSentMessage(
+            string testDestRef,
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+			//	AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode,
+			//[Values(true, false)]
+			bool doClear)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(ackMode))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					{
+						IMessageProducer producer = session.CreateProducer(destination);
+						ITextMessage message = session.CreateTextMessage();
+
+						string prefix = "ConsumerTest - TestDoChangeSentMessage: ";
+
+						for(int i = 0; i < COUNT; i++)
+						{
+							message.Properties[VALUE_NAME] = i;
+							message.Text = prefix + Convert.ToString(i);
+
+							producer.Send(message);
+
+							if(doClear)
+							{
+								message.ClearBody();
+								message.ClearProperties();
+							}
+						}
+
+						if(ackMode == AcknowledgementMode.Transactional)
+						{
+							session.Commit();
+						}
+
+						for(int i = 0; i < COUNT; i++)
+						{
+							ITextMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)) as ITextMessage;
+							Assert.AreEqual(msg.Text, prefix + Convert.ToString(i));
+							Assert.AreEqual(msg.Properties.GetInt(VALUE_NAME), i);
+						}
+
+						if(ackMode == AcknowledgementMode.Transactional)
+						{
+							session.Commit();
+						}
+
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestConsumerReceiveBeforeMessageDispatched(
+            string testDestRef,
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+			//	AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			// Launch a thread to perform a delayed send.
+			Thread sendThread = new Thread(DelayedProducerThreadProc);
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(ackMode))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					{
+						ThreadArg arg = new ThreadArg();
+
+						arg.connection = connection;
+						arg.session = session;
+						arg.destination = destination;
+
+						sendThread.Start(arg);
+						IMessage message = consumer.Receive(TimeSpan.FromMinutes(1));
+						Assert.IsNotNull(message);
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestDontStart(
+            string testDestRef,
+			//[Values(MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				ISession session = connection.CreateSession();
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+
+				// Send the messages
+				SendMessages(session, destination, deliveryMode, 1);
+
+				// Make sure no messages were delivered.
+				Assert.IsNull(consumer.Receive(TimeSpan.FromMilliseconds(1000)));
+			}
+		}
+
+		//[Test]
+		public virtual void TestSendReceiveTransacted(
+            string testDestRef,
+			//[Values(MsgDeliveryMode.NonPersistent, MsgDeliveryMode.Persistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				// Send a message to the broker.
+				connection.Start();
+				ISession session = connection.CreateSession(AcknowledgementMode.Transactional);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+				IMessageProducer producer = session.CreateProducer(destination);
+
+				producer.DeliveryMode = deliveryMode;
+				producer.Send(session.CreateTextMessage("Test"));
+
+				// Message should not be delivered until commit.
+				Thread.Sleep(1000);
+				Assert.IsNull(consumer.ReceiveNoWait());
+				session.Commit();
+
+				// Make sure only 1 message was delivered.
+				IMessage message = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNotNull(message);
+				Assert.IsFalse(message.NMSRedelivered);
+				Assert.IsNull(consumer.ReceiveNoWait());
+
+				// Message should be redelivered is rollback is used.
+				session.Rollback();
+
+				// Make sure only 1 message was delivered.
+				message = consumer.Receive(TimeSpan.FromMilliseconds(2000));
+				Assert.IsNotNull(message);
+				Assert.IsTrue(message.NMSRedelivered);
+				Assert.IsNull(consumer.ReceiveNoWait());
+
+				// If we commit now, the message should not be redelivered.
+				session.Commit();
+				Thread.Sleep(1000);
+				Assert.IsNull(consumer.ReceiveNoWait());
+			}
+		}
+
+		//[Test]
+		public virtual void TestAckedMessageAreConsumed(string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				ISession session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageProducer producer = session.CreateProducer(destination);
+				producer.Send(session.CreateTextMessage("Hello"));
+
+				// Consume the message...
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+				IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNotNull(msg);
+				msg.Acknowledge();
+
+				// Reset the session.
+				session.Close();
+				session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+
+				// Attempt to Consume the message...
+				consumer = session.CreateConsumer(destination);
+				msg = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNull(msg);
+
+				session.Close();
+			}
+		}
+
+		//[Test]
+		public virtual void TestLastMessageAcked(string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				ISession session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageProducer producer = session.CreateProducer(destination);
+				producer.Send(session.CreateTextMessage("Hello"));
+				producer.Send(session.CreateTextMessage("Hello2"));
+				producer.Send(session.CreateTextMessage("Hello3"));
+
+				// Consume the message...
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+				IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNotNull(msg);
+				msg = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNotNull(msg);
+				msg = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNotNull(msg);
+				msg.Acknowledge();
+
+				// Reset the session.
+				session.Close();
+				session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+
+				// Attempt to Consume the message...
+				consumer = session.CreateConsumer(destination);
+				msg = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNull(msg);
+
+				session.Close();
+			}
+		}
+
+		//[Test]
+		public virtual void TestUnAckedMessageAreNotConsumedOnSessionClose(string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				ISession session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageProducer producer = session.CreateProducer(destination);
+				producer.Send(session.CreateTextMessage("Hello"));
+
+				// Consume the message...
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+				IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNotNull(msg);
+				// Don't ack the message.
+
+				// Reset the session.  This should cause the unacknowledged message to be re-delivered.
+				session.Close();
+				session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+
+				// Attempt to Consume the message...
+				consumer = session.CreateConsumer(destination);
+				msg = consumer.Receive(TimeSpan.FromMilliseconds(2000));
+				Assert.IsNotNull(msg);
+				msg.Acknowledge();
+
+				session.Close();
+			}
+		}
+
+		//[Test]
+		public virtual void TestAsyncAckedMessageAreConsumed(string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				ISession session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageProducer producer = session.CreateProducer(destination);
+				producer.Send(session.CreateTextMessage("Hello"));
+
+				// Consume the message...
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+				consumer.Listener += new MessageListener(OnMessage);
+
+				Thread.Sleep(5000);
+
+				// Reset the session.
+				session.Close();
+
+				session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+
+				// Attempt to Consume the message...
+				consumer = session.CreateConsumer(destination);
+				IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+				Assert.IsNull(msg);
+
+				session.Close();
+			}
+		}
+
+		//[Test]
+		public virtual void TestAsyncUnAckedMessageAreNotConsumedOnSessionClose(string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				// don't aknowledge message on onMessage() call
+				dontAck = true;
+				ISession session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageProducer producer = session.CreateProducer(destination);
+				producer.Send(session.CreateTextMessage("Hello"));
+
+				// Consume the message...
+				using(IMessageConsumer consumer = session.CreateConsumer(destination))
+				{
+					consumer.Listener += new MessageListener(OnMessage);
+					// Don't ack the message.
+				}
+
+				// Reset the session. This should cause the Unacked message to be
+				// redelivered.
+				session.Close();
+
+				Thread.Sleep(5000);
+				session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+				// Attempt to Consume the message...
+				using(IMessageConsumer consumer = session.CreateConsumer(destination))
+				{
+					IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000));
+					Assert.IsNotNull(msg);
+					msg.Acknowledge();
+				}
+
+				session.Close();
+			}
+		}
+
+		//[Test]
+		public virtual void TestAddRemoveAsnycMessageListener(DestinationType destType, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+
+				ISession session = connection.CreateSession(AcknowledgementMode.ClientAcknowledge);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+
+				consumer.Listener += OnMessage;
+				consumer.Listener -= OnMessage;
+				consumer.Listener += OnMessage;
+
+				consumer.Close();
+			}
+		}
+
+		public void OnMessage(IMessage message)
+		{
+			Assert.IsNotNull(message);
+
+			if(!dontAck)
+			{
+				try
+				{
+					message.Acknowledge();
+				}
+				catch(Exception)
+				{
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestReceiveNoWait(
+            string testDestRef,
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+			//	AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode,
+			//[Values(MsgDeliveryMode.NonPersistent, MsgDeliveryMode.Persistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			const int RETRIES = 20;
+
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(ackMode))
+				{
+				    IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						ITextMessage message = session.CreateTextMessage("TEST");
+						producer.Send(message);
+
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							session.Commit();
+						}
+					}
+
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					{
+						IMessage message = null;
+
+						for(int i = 0; i < RETRIES && message == null; ++i)
+						{
+							message = consumer.ReceiveNoWait();
+							Thread.Sleep(100);
+						}
+
+						Assert.IsNotNull(message);
+						message.Acknowledge();
+
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							session.Commit();
+						}
+					}
+				}
+			}
+		}
+
+#endif
+
+    }
+}
diff --git a/src/test/csharp/DurableTest.cs b/src/test/csharp/DurableTest.cs
new file mode 100644
index 0000000..aa38931
--- /dev/null
+++ b/src/test/csharp/DurableTest.cs
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Threading;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class DurableTest : NMSTest
+	{
+		protected static string DURABLE_SELECTOR = "2 > 1";
+
+		protected string TEST_CLIENT_AND_CONSUMER_ID;
+		protected string SEND_CLIENT_ID;
+
+		protected DurableTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[SetUp]
+		public override void SetUp()
+		{
+			base.SetUp();
+			
+			TEST_CLIENT_AND_CONSUMER_ID = GetTestClientId();
+			SEND_CLIENT_ID = GetTestClientId();
+		}
+
+		//[Test]
+		public virtual void TestSendWhileClosed(
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+			//	AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode, string testTopicRef)
+		{
+			try
+			{				
+		        using(IConnection connection = CreateConnection(TEST_CLIENT_AND_CONSUMER_ID))
+				{
+			        connection.Start();
+
+					using(ISession session = connection.CreateSession(ackMode))
+					{
+						ITopic topic = (ITopic)GetClearDestinationByNodeReference(session, testTopicRef);
+						IMessageProducer producer = session.CreateProducer(topic);
+
+						producer.DeliveryMode = MsgDeliveryMode.Persistent;
+										
+				        ISession consumeSession = connection.CreateSession(ackMode);
+				        IMessageConsumer consumer = consumeSession.CreateDurableConsumer(topic, TEST_CLIENT_AND_CONSUMER_ID, null, false);
+				        Thread.Sleep(1000);
+				        consumer.Dispose();
+						consumer = null;
+				        
+						ITextMessage message = session.CreateTextMessage("DurableTest-TestSendWhileClosed");
+				        message.Properties.SetString("test", "test");
+				        message.NMSType = "test";
+				        producer.Send(message);
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							session.Commit();
+						}
+										        
+				        Thread.Sleep(1000);
+						consumer = consumeSession.CreateDurableConsumer(topic, TEST_CLIENT_AND_CONSUMER_ID, null, false);
+				        ITextMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(1000)) as ITextMessage;
+						msg.Acknowledge();
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							consumeSession.Commit();
+						}
+						
+						Assert.IsNotNull(msg);
+				        Assert.AreEqual(msg.Text, "DurableTest-TestSendWhileClosed");
+				        Assert.AreEqual(msg.NMSType, "test");
+				        Assert.AreEqual(msg.Properties.GetString("test"), "test");
+					}
+				}
+			}
+			catch(Exception ex)
+			{
+				Assert.Fail(ex.Message);
+			}
+			finally
+			{
+                // Pause to allow Stomp to unregister at the broker.
+                Thread.Sleep(500);
+
+				UnregisterDurableConsumer(TEST_CLIENT_AND_CONSUMER_ID, TEST_CLIENT_AND_CONSUMER_ID);
+			}			
+	    }		
+		
+		//[Test]
+		public void TestDurableConsumerSelectorChange(
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+			//	AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode, string testTopicRef)
+		{
+			try
+			{
+				using(IConnection connection = CreateConnection(TEST_CLIENT_AND_CONSUMER_ID))
+				{
+					connection.Start();
+					using(ISession session = connection.CreateSession(ackMode))
+					{
+						ITopic topic = (ITopic)GetClearDestinationByNodeReference(session, testTopicRef);
+						IMessageProducer producer = session.CreateProducer(topic);
+						IMessageConsumer consumer = session.CreateDurableConsumer(topic, TEST_CLIENT_AND_CONSUMER_ID, "color='red'", false);
+
+						producer.DeliveryMode = MsgDeliveryMode.Persistent;
+
+						// Send the messages
+						ITextMessage sendMessage = session.CreateTextMessage("1st");
+						sendMessage.Properties["color"] = "red";
+						producer.Send(sendMessage);
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							session.Commit();
+						}
+
+						ITextMessage receiveMsg = consumer.Receive(receiveTimeout) as ITextMessage;
+						Assert.IsNotNull(receiveMsg, "Failed to retrieve 1st durable message.");
+						Assert.AreEqual("1st", receiveMsg.Text);
+						Assert.AreEqual(MsgDeliveryMode.Persistent, receiveMsg.NMSDeliveryMode, "NMSDeliveryMode does not match");
+						receiveMsg.Acknowledge();
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							session.Commit();
+						}
+
+						// Change the subscription, allowing some time for the Broker to purge the
+						// consumers resources.
+						consumer.Dispose();
+                        Thread.Sleep(1000);
+						
+						consumer = session.CreateDurableConsumer(topic, TEST_CLIENT_AND_CONSUMER_ID, "color='blue'", false);
+
+						sendMessage = session.CreateTextMessage("2nd");
+						sendMessage.Properties["color"] = "red";
+						producer.Send(sendMessage);
+						sendMessage = session.CreateTextMessage("3rd");
+						sendMessage.Properties["color"] = "blue";
+						producer.Send(sendMessage);
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							session.Commit();
+						}
+
+						// Selector should skip the 2nd message.
+						receiveMsg = consumer.Receive(receiveTimeout) as ITextMessage;
+						Assert.IsNotNull(receiveMsg, "Failed to retrieve durable message.");
+						Assert.AreEqual("3rd", receiveMsg.Text, "Retrieved the wrong durable message.");
+						Assert.AreEqual(MsgDeliveryMode.Persistent, receiveMsg.NMSDeliveryMode, "NMSDeliveryMode does not match");
+						receiveMsg.Acknowledge();
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							session.Commit();
+						}
+
+						// Make sure there are no pending messages.
+						Assert.IsNull(consumer.ReceiveNoWait(), "Wrong number of messages in durable subscription.");
+					}
+				}
+			}
+			catch(Exception ex)
+			{
+				Assert.Fail(ex.Message);
+			}
+			finally
+			{
+                // Pause to allow Stomp to unregister at the broker.
+                Thread.Sleep(500);
+
+				UnregisterDurableConsumer(TEST_CLIENT_AND_CONSUMER_ID, TEST_CLIENT_AND_CONSUMER_ID);
+			}
+		}
+
+		//[Test]
+		public void TestDurableConsumer(
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+			//	AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode, string testDurableTopicName)
+		{
+			try
+			{
+				RegisterDurableConsumer(TEST_CLIENT_AND_CONSUMER_ID, testDurableTopicName, TEST_CLIENT_AND_CONSUMER_ID, null, false);
+				RunTestDurableConsumer(testDurableTopicName, ackMode);
+				if(AcknowledgementMode.Transactional == ackMode)
+				{
+					RunTestDurableConsumer(testDurableTopicName, ackMode);
+				}
+			}
+			finally
+			{
+                // Pause to allow Stomp to unregister at the broker.
+                Thread.Sleep(500);
+				
+				UnregisterDurableConsumer(TEST_CLIENT_AND_CONSUMER_ID, TEST_CLIENT_AND_CONSUMER_ID);
+			}
+		}
+
+		protected void RunTestDurableConsumer(string topicName, AcknowledgementMode ackMode)
+		{
+			SendDurableMessage(topicName);
+			SendDurableMessage(topicName);
+
+			using(IConnection connection = CreateConnection(TEST_CLIENT_AND_CONSUMER_ID))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(ackMode))
+				{
+					ITopic topic = SessionUtil.GetTopic(session, topicName);
+					using(IMessageConsumer consumer = session.CreateDurableConsumer(topic, TEST_CLIENT_AND_CONSUMER_ID, null, false))
+					{
+						IMessage msg = consumer.Receive(receiveTimeout);
+						Assert.IsNotNull(msg, "Did not receive first durable message.");
+						msg.Acknowledge();
+
+						msg = consumer.Receive(receiveTimeout);
+						Assert.IsNotNull(msg, "Did not receive second durable message.");
+						msg.Acknowledge();
+
+						if(AcknowledgementMode.Transactional == ackMode)
+						{
+							session.Commit();
+						}
+					}
+				}
+			}
+		}
+
+		protected void SendDurableMessage(string topicName)
+		{
+			using(IConnection connection = CreateConnection(SEND_CLIENT_ID))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession())
+				{
+					ITopic topic = SessionUtil.GetTopic(session, topicName);
+					using(IMessageProducer producer = session.CreateProducer(topic))
+					{
+						ITextMessage message = session.CreateTextMessage("Durable Hello");
+
+						producer.DeliveryMode = MsgDeliveryMode.Persistent;
+						producer.Send(message);
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/test/csharp/EndianBinaryReaderTest.cs b/src/test/csharp/EndianBinaryReaderTest.cs
new file mode 100644
index 0000000..d2b392a
--- /dev/null
+++ b/src/test/csharp/EndianBinaryReaderTest.cs
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.IO;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	[TestFixture]
+	public class EndianBinaryReaderTest
+	{
+		public void readString16Helper(byte[] input, char[] expect)
+		{
+			MemoryStream stream = new MemoryStream(input);
+			EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+			char[] result = reader.ReadString16().ToCharArray();
+
+			for(int i = 0; i < expect.Length; ++i)
+			{
+				Assert.AreEqual(expect[i], result[i]);
+			}
+		}
+
+		[Test]
+		public void testReadString16_1byteUTF8encoding()
+		{
+			// Test data with 1-byte UTF8 encoding.
+			char[] expect = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
+			byte[] input = { 0x00, 0x0E, 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+
+			readString16Helper(input, expect);
+		}
+
+		[Test]
+		public void testReadString16_2byteUTF8encoding()
+		{
+			// Test data with 2-byte UT8 encoding.
+			char[] expect = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
+			byte[] input = { 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+			readString16Helper(input, expect);
+		}
+
+		[Test]
+		public void testReadString16_1byteAnd2byteEmbeddedNULLs()
+		{
+			// Test data with 1-byte and 2-byte encoding with embedded NULL's.
+			char[] expect = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
+			byte[] input = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+			readString16Helper(input, expect);
+		}
+
+		[Test]
+		[ExpectedException(typeof(IOException))]
+		public void testReadString16_UTF8Missing2ndByte()
+		{
+			// Test with bad UTF-8 encoding, missing 2nd byte of two byte value
+			byte[] input = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+			MemoryStream stream = new MemoryStream(input);
+			EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+			reader.ReadString16();
+		}
+
+		[Test]
+		[ExpectedException(typeof(IOException))]
+		public void testReadString16_3byteEncodingMissingLastByte()
+		{
+			// Test with three byte encode that's missing a last byte.
+			byte[] input = { 0x00, 0x02, 0xE8, 0xA8 };
+
+			MemoryStream stream = new MemoryStream(input);
+			EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+			reader.ReadString16();
+		}
+
+		public void readString32Helper(byte[] input, char[] expect)
+		{
+			MemoryStream stream = new MemoryStream(input);
+			EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+			char[] result = reader.ReadString32().ToCharArray();
+
+			for(int i = 0; i < expect.Length; ++i)
+			{
+				Assert.AreEqual(expect[i], result[i]);
+			}
+		}
+
+		[Test]
+		public void testReadString32_1byteUTF8encoding()
+		{
+			// Test data with 1-byte UTF8 encoding.
+			char[] expect = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
+			byte[] input = { 0x00, 0x00, 0x00, 0x0E, 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+
+			readString32Helper(input, expect);
+		}
+
+		[Test]
+		public void testReadString32_2byteUTF8encoding()
+		{
+			// Test data with 2-byte UT8 encoding.
+			char[] expect = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
+			byte[] input = { 0x00, 0x00, 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+			readString32Helper(input, expect);
+		}
+
+		[Test]
+		public void testReadString32_1byteAnd2byteEmbeddedNULLs()
+		{
+			// Test data with 1-byte and 2-byte encoding with embedded NULL's.
+			char[] expect = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
+			byte[] input = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+			readString32Helper(input, expect);
+		}
+
+		[Test]
+		[ExpectedException(typeof(IOException))]
+		public void testReadString32_UTF8Missing2ndByte()
+		{
+			// Test with bad UTF-8 encoding, missing 2nd byte of two byte value
+			byte[] input = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+			MemoryStream stream = new MemoryStream(input);
+			EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+			reader.ReadString32();
+		}
+
+		[Test]
+		[ExpectedException(typeof(IOException))]
+		public void testReadString32_3byteEncodingMissingLastByte()
+		{
+			// Test with three byte encode that's missing a last byte.
+			byte[] input = { 0x00, 0x00, 0x00, 0x02, 0xE8, 0xA8 };
+
+			MemoryStream stream = new MemoryStream(input);
+			EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+			reader.ReadString32();
+		}
+	}
+}
diff --git a/src/test/csharp/EndianBinaryWriterTest.cs b/src/test/csharp/EndianBinaryWriterTest.cs
new file mode 100644
index 0000000..5baf66f
--- /dev/null
+++ b/src/test/csharp/EndianBinaryWriterTest.cs
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.IO;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	[TestFixture]
+	public class EndianBinaryWriterTest
+	{
+		void writeString16TestHelper(char[] input, byte[] expect)
+		{
+			MemoryStream stream = new MemoryStream();
+			EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+
+			String str = new String(input);
+
+			writer.WriteString16(str);
+
+			byte[] result = stream.GetBuffer();
+
+			Assert.AreEqual(result[0], 0x00);
+			Assert.AreEqual(result[1], expect.Length);
+
+			for(int i = 4; i < expect.Length; ++i)
+			{
+				Assert.AreEqual(result[i], expect[i - 2]);
+			}
+		}
+
+		[Test]
+		public void testWriteString16_1byteUTF8encoding()
+		{
+			// Test data with 1-byte UTF8 encoding.
+			char[] input = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
+			byte[] expect = { 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+
+			writeString16TestHelper(input, expect);
+		}
+
+		[Test]
+		public void testWriteString16_2byteUTF8encoding()
+		{
+			// Test data with 2-byte UT8 encoding.
+			char[] input = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
+			byte[] expect = { 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+
+			writeString16TestHelper(input, expect);
+		}
+
+		[Test]
+		public void testWriteString16_1byteAnd2byteEmbeddedNULLs()
+		{
+			// Test data with 1-byte and 2-byte encoding with embedded NULL's.
+			char[] input = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
+			byte[] expect = { 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+			writeString16TestHelper(input, expect);
+		}
+
+		[Test]
+		public void testWriteString16_nullstring()
+		{
+			// test that a null string writes no output.
+			MemoryStream stream = new MemoryStream();
+			EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+			writer.WriteString16(null);
+			Assert.AreEqual(0, stream.Length);
+		}
+
+		[Test]
+		public void testWriteString16_emptystring()
+		{
+			// test that a null string writes no output.
+			MemoryStream stream = new MemoryStream();
+			EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+			writer.WriteString16("");
+
+			stream.Seek(0, SeekOrigin.Begin);
+			EndianBinaryReader reader = new EndianBinaryReader(stream);
+			Assert.AreEqual(0, reader.ReadInt16());
+		}
+
+		[Test]
+		[ExpectedException(typeof(IOException))]
+		public void testWriteString16_stringTooLong()
+		{
+			// String of length 65536 of Null Characters.
+			MemoryStream stream = new MemoryStream();
+			EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+			String testStr = new String('a', 65536);
+			writer.Write(testStr);
+		}
+
+		[Test]
+		public void testWriteString16_maxStringLength()
+		{
+			// String of length 65535 of non Null Characters since Null encodes as UTF-8.
+			MemoryStream stream = new MemoryStream();
+			EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+			String testStr = new String('a', 65535);
+			writer.Write(testStr);
+		}
+
+		[Test]
+		[ExpectedException(typeof(IOException))]
+		public void testWriteString16_invalidEncodingHeader()
+		{
+			// Set one of the 65535 bytes to a value that will result in a 2 byte UTF8 encoded sequence.
+			// This will cause the string of length 65535 to have a utf length of 65536.
+			MemoryStream stream = new MemoryStream();
+			EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+			String testStr = new String('a', 65535);
+			char[] array = testStr.ToCharArray();
+			array[0] = '\u0000';
+			testStr = new String(array);
+			writer.Write(testStr);
+		}
+
+		void writeString32TestHelper(char[] input, byte[] expect)
+		{
+			MemoryStream stream = new MemoryStream();
+			EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+
+			String str = new String(input);
+
+			writer.WriteString32(str);
+
+			byte[] result = stream.GetBuffer();
+
+			Assert.AreEqual(result[0], 0x00);
+			Assert.AreEqual(result[1], 0x00);
+			Assert.AreEqual(result[2], 0x00);
+			Assert.AreEqual(result[3], expect.Length);
+
+			for(int i = 4; i < expect.Length; ++i)
+			{
+				Assert.AreEqual(result[i], expect[i - 4]);
+			}
+		}
+
+		[Test]
+		public void testWriteString32_1byteUTF8encoding()
+		{
+			// Test data with 1-byte UTF8 encoding.
+			char[] input = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
+			byte[] expect = { 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+
+			writeString32TestHelper(input, expect);
+		}
+
+		[Test]
+		public void testWriteString32_2byteUTF8encoding()
+		{
+			// Test data with 2-byte UT8 encoding.
+			char[] input = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
+			byte[] expect = { 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+
+			writeString32TestHelper(input, expect);
+		}
+
+		[Test]
+		public void testWriteString32_1byteAnd2byteEmbeddedNULLs()
+		{
+			// Test data with 1-byte and 2-byte encoding with embedded NULL's.
+			char[] input = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
+			byte[] expect = { 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+			writeString32TestHelper(input, expect);
+		}
+
+		[Test]
+		public void testWriteString32_nullstring()
+		{
+			// test that a null strings writes a -1
+			MemoryStream stream = new MemoryStream();
+			EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+			writer.WriteString32(null);
+
+			stream.Seek(0, SeekOrigin.Begin);
+			EndianBinaryReader reader = new EndianBinaryReader(stream);
+			Assert.AreEqual(-1, reader.ReadInt32());
+		}
+	}
+}
diff --git a/src/test/csharp/EndianTest.cs b/src/test/csharp/EndianTest.cs
new file mode 100644
index 0000000..ad9ce08
--- /dev/null
+++ b/src/test/csharp/EndianTest.cs
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System.IO;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	[TestFixture]
+	public class EndianTest
+	{
+		[Test]
+		public void TestLongEndian()
+		{
+			long value = 0x0102030405060708L;
+			long newValue = EndianSupport.SwitchEndian(value);
+			Assert.AreEqual(0x0807060504030201L, newValue);
+			long actual = EndianSupport.SwitchEndian(newValue);
+			Assert.AreEqual(value, actual);
+		}
+
+		[Test]
+		public void TestIntEndian()
+		{
+			int value = 0x12345678;
+			int newValue = EndianSupport.SwitchEndian(value);
+			Assert.AreEqual(0x78563412, newValue);
+			int actual = EndianSupport.SwitchEndian(newValue);
+			Assert.AreEqual(value, actual);
+		}
+
+		[Test]
+		public void TestCharEndian()
+		{
+			char value = 'J';
+			char newValue = EndianSupport.SwitchEndian(value);
+			char actual = EndianSupport.SwitchEndian(newValue);
+			Assert.AreEqual(value, actual);
+		}
+
+		[Test]
+		public void TestShortEndian()
+		{
+			short value = 0x1234;
+			short newValue = EndianSupport.SwitchEndian(value);
+			Assert.AreEqual(0x3412, newValue);
+			short actual = EndianSupport.SwitchEndian(newValue);
+			Assert.AreEqual(value, actual);
+		}
+
+		[Test]
+		public void TestNegativeLongEndian()
+		{
+			long value = -0x0102030405060708L;
+			long newValue = EndianSupport.SwitchEndian(value);
+			long actual = EndianSupport.SwitchEndian(newValue);
+			Assert.AreEqual(value, actual);
+		}
+
+		[Test]
+		public void TestNegativeIntEndian()
+		{
+			int value = -0x12345678;
+			int newValue = EndianSupport.SwitchEndian(value);
+			int actual = EndianSupport.SwitchEndian(newValue);
+			Assert.AreEqual(value, actual);
+		}
+
+		[Test]
+		public void TestNegativeShortEndian()
+		{
+			short value = -0x1234;
+			short newValue = EndianSupport.SwitchEndian(value);
+			short actual = EndianSupport.SwitchEndian(newValue);
+			Assert.AreEqual(value, actual);
+		}
+
+		[Test]
+		public void TestFloatDontNeedEndianSwitch()
+		{
+			float value = -1.223F;
+
+			// Convert to int so we can compare to Java version.
+			MemoryStream ms = new MemoryStream(4);
+			BinaryWriter bw = new BinaryWriter(ms);
+			bw.Write(value);
+			bw.Close();
+			ms = new MemoryStream(ms.ToArray());
+			BinaryReader br = new BinaryReader(ms);
+
+			// System.out.println(Integer.toString(Float.floatToIntBits(-1.223F), 16));
+			Assert.AreEqual(-0x406374bc, br.ReadInt32());
+		}
+
+		[Test]
+		public void TestDoublDontNeedEndianSwitch()
+		{
+			double value = -1.223D;
+
+			// Convert to int so we can compare to Java version.
+			MemoryStream ms = new MemoryStream(4);
+			BinaryWriter bw = new BinaryWriter(ms);
+			bw.Write(value);
+			bw.Close();
+			ms = new MemoryStream(ms.ToArray());
+			BinaryReader br = new BinaryReader(ms);
+			long longVersion = br.ReadInt64();
+
+			// System.out.println(Long.toString(Double.doubleToLongBits(-1.223D), 16));
+			Assert.AreEqual(-0x400c6e978d4fdf3b, longVersion);
+		}
+	}
+}
+
+
+
diff --git a/src/test/csharp/ForeignMessageTransformationTest.cs b/src/test/csharp/ForeignMessageTransformationTest.cs
new file mode 100644
index 0000000..225ae88
--- /dev/null
+++ b/src/test/csharp/ForeignMessageTransformationTest.cs
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using Apache.NMS.Commands;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+    //[TestFixture]
+    public class ForeignMessageTransformationTest : NMSTest
+    {
+        private string propertyName = "Test-Property";
+        private string propertyValue = "Test-Property-Value";
+        private string mapElementName = "Test-Map-Property";
+        private string mapElementValue = "Test-Map-Property-Value";
+        private string textBody = "This is a TextMessage from a Foreign Provider";
+        private byte[] bytesContent = {1, 2, 3, 4, 5, 6, 7, 8};
+
+        private bool a = true;
+        private byte b = 123;
+        private char c = 'c';
+        private short d = 0x1234;
+        private int e = 0x12345678;
+        private long f = 0x1234567812345678;
+        private string g = "Hello World!";
+        private bool h = false;
+        private byte i = 0xFF;
+        private short j = -0x1234;
+        private int k = -0x12345678;
+        private long l = -0x1234567812345678;
+        private float m = 2.1F;
+        private double n = 2.3;
+
+		protected ForeignMessageTransformationTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+        //[Test]
+        public virtual void TestSendReceiveForeignMessage(
+            //[Values(DEFAULT_TEST_QUEUE, DEFAULT_TEST_TOPIC)]
+            string testDestRef,
+            //[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+            MsgDeliveryMode deliveryMode)
+        {
+            using(IConnection connection = CreateConnection())
+            {
+                connection.Start();
+                using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+                {
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+                    using(IMessageConsumer consumer = session.CreateConsumer(destination))
+                    using(IMessageProducer producer = session.CreateProducer(destination))
+                    {
+                        try
+                        {
+                            producer.DeliveryMode = deliveryMode;
+                            Message request = new Message();
+                            request.Properties[propertyName] = propertyValue;
+
+                            producer.Send(request);
+
+                            IMessage message = consumer.Receive(receiveTimeout);
+                            Assert.IsNotNull(message, "No message returned!");
+                            Assert.AreEqual(request.Properties.Count, message.Properties.Count, "Invalid number of properties.");
+                            Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+                            // use generic API to access entries
+                            Assert.AreEqual(propertyValue, message.Properties[propertyName], "generic map entry: " + propertyName);
+
+                            // use type safe APIs
+                            Assert.AreEqual(propertyValue, message.Properties.GetString(propertyName),   "map entry: " + propertyName);
+                        }
+                        catch(NotSupportedException)
+                        {
+                        }
+                    }
+                }
+            }
+        }
+
+        //[Test]
+        public virtual void TestSendReceiveForeignTextMessage(
+            //[Values(DEFAULT_TEST_QUEUE, DEFAULT_TEST_TOPIC)]
+            string testDestRef,
+            //[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+            MsgDeliveryMode deliveryMode)
+        {
+            using(IConnection connection = CreateConnection())
+            {
+                connection.Start();
+                using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+                {
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+                    using(IMessageConsumer consumer = session.CreateConsumer(destination))
+                    using(IMessageProducer producer = session.CreateProducer(destination))
+                    {
+                        try
+                        {
+                            producer.DeliveryMode = deliveryMode;
+                            TextMessage request = new TextMessage();
+                            request.Properties[propertyName] = propertyValue;
+                            request.Text = textBody;
+
+                            producer.Send(request);
+
+                            ITextMessage message = consumer.Receive(receiveTimeout) as ITextMessage;
+                            Assert.IsNotNull(message, "No message returned!");
+                            Assert.AreEqual(request.Properties.Count, message.Properties.Count, "Invalid number of properties.");
+                            Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+                            // Check the body
+                            Assert.AreEqual(textBody, message.Text, "TextMessage body was wrong.");
+
+                            // use generic API to access entries
+                            Assert.AreEqual(propertyValue, message.Properties[propertyName], "generic map entry: " + propertyName);
+
+                            // use type safe APIs
+                            Assert.AreEqual(propertyValue, message.Properties.GetString(propertyName),   "map entry: " + propertyName);
+                        }
+                        catch(NotSupportedException)
+                        {
+                        }
+                    }
+                }
+            }
+        }
+
+		//[Test]
+		public virtual void TestSendReceiveForeignBytesMessage(
+            //[Values(DEFAULT_TEST_QUEUE, DEFAULT_TEST_TOPIC)]
+            string testDestRef,
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						try
+						{
+							producer.DeliveryMode = deliveryMode;
+							BytesMessage request = new BytesMessage();
+							request.Properties[propertyName] = propertyValue;
+							request.WriteBytes(bytesContent);
+
+							producer.Send(request);
+
+							IBytesMessage message = consumer.Receive(receiveTimeout) as IBytesMessage;
+							Assert.IsNotNull(message, "No message returned!");
+							Assert.AreEqual(request.Properties.Count, message.Properties.Count, "Invalid number of properties.");
+							Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+							// Check the body
+							byte[] content = new byte[bytesContent.Length];
+							Assert.AreEqual(bytesContent.Length, message.ReadBytes(content));
+							Assert.AreEqual(bytesContent, content, "BytesMessage body was wrong.");
+
+							// use generic API to access entries
+							Assert.AreEqual(propertyValue, message.Properties[propertyName], "generic map entry: " + propertyName);
+
+							// use type safe APIs
+							Assert.AreEqual(propertyValue, message.Properties.GetString(propertyName),   "map entry: " + propertyName);
+						}
+						catch(NotSupportedException)
+						{
+						}
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestSendReceiveForeignMapMessage(
+            //[Values(DEFAULT_TEST_QUEUE, DEFAULT_TEST_TOPIC)]
+            string testDestRef,
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						try
+						{
+							producer.DeliveryMode = deliveryMode;
+							MapMessage request = new MapMessage();
+							request.Properties[propertyName] = propertyValue;
+							request.Body[mapElementName] = mapElementValue;
+
+							producer.Send(request);
+
+							IMapMessage message = consumer.Receive(receiveTimeout) as IMapMessage;
+							Assert.IsNotNull(message, "No message returned!");
+							Assert.AreEqual(request.Properties.Count, message.Properties.Count, "Invalid number of properties.");
+							Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+							// Check the body
+							Assert.AreEqual(request.Body.Count, message.Body.Count);
+							Assert.AreEqual(mapElementValue, message.Body[mapElementName], "MapMessage body was wrong.");
+
+							// use generic API to access entries
+							Assert.AreEqual(propertyValue, message.Properties[propertyName], "generic map entry: " + propertyName);
+
+							// use type safe APIs
+							Assert.AreEqual(propertyValue, message.Properties.GetString(propertyName),   "map entry: " + propertyName);
+						}
+						catch(NotSupportedException)
+						{
+						}
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestSendReceiveForeignStreamMessage(
+            //[Values(DEFAULT_TEST_QUEUE, DEFAULT_TEST_TOPIC)]
+            string testDestRef,
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						try
+						{
+							producer.DeliveryMode = deliveryMode;
+							StreamMessage request = new StreamMessage();
+							request.Properties[propertyName] = propertyValue;
+
+							request.WriteBoolean(a);
+							request.WriteByte(b);
+							request.WriteChar(c);
+							request.WriteInt16(d);
+							request.WriteInt32(e);
+							request.WriteInt64(f);
+							request.WriteString(g);
+							request.WriteBoolean(h);
+							request.WriteByte(i);
+							request.WriteInt16(j);
+							request.WriteInt32(k);
+							request.WriteInt64(l);
+							request.WriteSingle(m);
+							request.WriteDouble(n);
+
+							producer.Send(request);
+
+							IStreamMessage message = consumer.Receive(receiveTimeout) as IStreamMessage;
+							Assert.IsNotNull(message, "No message returned!");
+							Assert.AreEqual(request.Properties.Count, message.Properties.Count, "Invalid number of properties.");
+							Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+							// Check the body
+							Assert.AreEqual(a, message.ReadBoolean(), "Stream Boolean Value: a");
+							Assert.AreEqual(b, message.ReadByte(), "Stream Byte Value: b");
+							Assert.AreEqual(c, message.ReadChar(), "Stream Char Value: c");
+							Assert.AreEqual(d, message.ReadInt16(), "Stream Int16 Value: d");
+							Assert.AreEqual(e, message.ReadInt32(), "Stream Int32 Value: e");
+							Assert.AreEqual(f, message.ReadInt64(), "Stream Int64 Value: f");
+							Assert.AreEqual(g, message.ReadString(), "Stream String Value: g");
+							Assert.AreEqual(h, message.ReadBoolean(), "Stream Boolean Value: h");
+							Assert.AreEqual(i, message.ReadByte(), "Stream Byte Value: i");
+							Assert.AreEqual(j, message.ReadInt16(), "Stream Int16 Value: j");
+							Assert.AreEqual(k, message.ReadInt32(), "Stream Int32 Value: k");
+							Assert.AreEqual(l, message.ReadInt64(), "Stream Int64 Value: l");
+							Assert.AreEqual(m, message.ReadSingle(), "Stream Single Value: m");
+							Assert.AreEqual(n, message.ReadDouble(), "Stream Double Value: n");
+
+							// use generic API to access entries
+							Assert.AreEqual(propertyValue, message.Properties[propertyName], "generic map entry: " + propertyName);
+
+							// use type safe APIs
+							Assert.AreEqual(propertyValue, message.Properties.GetString(propertyName),   "map entry: " + propertyName);
+						}
+						catch(NotSupportedException)
+						{
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQAsyncConsumeTest.cs b/src/test/csharp/MSMQAsyncConsumeTest.cs
new file mode 100644
index 0000000..4aabb1e
--- /dev/null
+++ b/src/test/csharp/MSMQAsyncConsumeTest.cs
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Threading;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQAsyncConsumeTest : AsyncConsumeTest
+	{
+		protected static string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+
+		public MSMQAsyncConsumeTest() :
+			base(new MSMQTestSupport())
+		{
+		}
+
+		[SetUp]
+		public override void SetUp()
+		{
+			base.SetUp();
+		}
+
+		[TearDown]
+		public override void TearDown()
+		{
+			base.TearDown();
+		}
+
+		[Test]
+		public void TestAsynchronousConsume(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestAsynchronousConsume(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public void TestCreateConsumerAfterSend(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestCreateConsumerAfterSend(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public void TestCreateConsumerBeforeSendAddListenerAfterSend(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestCreateConsumerBeforeSendAddListenerAfterSend(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public void TestAsynchronousTextMessageConsume(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestAsynchronousTextMessageConsume(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+        [Ignore("Temporary queues are not supported")]
+		public void TestTemporaryQueueAsynchronousConsume(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			using(IConnection connection = CreateConnectionAndStart(GetTestClientId()))
+			using(ISession syncSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(ISession asyncSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+			using(IDestination destination = GetClearDestinationByNodeReference(syncSession, DEFAULT_TEST_QUEUE))
+			using(ITemporaryQueue tempReplyDestination = syncSession.CreateTemporaryQueue())
+			using(IMessageConsumer consumer = asyncSession.CreateConsumer(destination))
+			using(IMessageConsumer tempConsumer = asyncSession.CreateConsumer(tempReplyDestination))
+			using(IMessageProducer producer = syncSession.CreateProducer(destination))
+			{
+				producer.DeliveryMode = deliveryMode;
+				tempConsumer.Listener += new MessageListener(OnMessage);
+				consumer.Listener += new MessageListener(OnQueueMessage);
+
+				IMessage request = syncSession.CreateMessage();
+				request.NMSCorrelationID = "TemqQueueAsyncConsume";
+				request.NMSType = "Test";
+				request.NMSReplyTo = tempReplyDestination;
+				producer.Send(request);
+
+				WaitForMessageToArrive();
+				Assert.AreEqual("TempQueueAsyncResponse", receivedMsg.NMSCorrelationID, "Invalid correlation ID.");
+			}
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQBadConsumeTest.cs b/src/test/csharp/MSMQBadConsumeTest.cs
new file mode 100644
index 0000000..b8e9089
--- /dev/null
+++ b/src/test/csharp/MSMQBadConsumeTest.cs
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using NUnit.Framework;
+using Apache.NMS.Test;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQBadConsumeTest : BadConsumeTest
+	{
+		public MSMQBadConsumeTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[SetUp]
+		public override void SetUp()
+		{
+			base.SetUp();
+		}
+
+		[TearDown]
+		public override void TearDown()
+		{
+			base.TearDown();
+		}
+
+		[Test]
+		[ExpectedException(Handler="ExceptionValidationCheck")]
+		public override void TestBadConsumerException()
+		{
+			base.TestBadConsumerException();
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQBytesMessageTest.cs b/src/test/csharp/MSMQBytesMessageTest.cs
new file mode 100644
index 0000000..5c58bc9
--- /dev/null
+++ b/src/test/csharp/MSMQBytesMessageTest.cs
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using Apache.NMS.Util;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQBytesMessageTest : BytesMessageTest
+	{
+		protected static string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+
+		public MSMQBytesMessageTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		public void SendReceiveBytesMessage(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.SendReceiveBytesMessage(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+
+        [Test]
+        public void SendReceiveBytesMessageContent(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+        {
+			base.SendReceiveBytesMessageContent(deliveryMode, DEFAULT_TEST_QUEUE);
+        }
+	}
+}
diff --git a/src/test/csharp/MSMQConnectionTest.cs b/src/test/csharp/MSMQConnectionTest.cs
new file mode 100644
index 0000000..cc3d2d4
--- /dev/null
+++ b/src/test/csharp/MSMQConnectionTest.cs
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQConnectionTest : ConnectionTest
+	{
+		protected const string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+		protected const string DEFAULT_TEST_TOPIC = "defaultTestTopic";
+
+		public MSMQConnectionTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[SetUp]
+		public override void SetUp()
+		{
+			base.SetUp();
+		}
+	
+		[TearDown]
+		public override void TearDown()
+		{
+			base.TearDown();
+		}
+	
+		/// <summary>
+		/// Verify that it is possible to create multiple connections to the broker.
+		/// There was a bug in the connection factory which set the clientId member which made
+		/// it impossible to create an additional connection.
+		/// </summary>
+		[Test]
+		public override void TestTwoConnections()
+		{
+			base.TestTwoConnections();
+		}
+	
+		[Test]
+		public void TestCreateAndDisposeWithConsumer(
+			[Values(true, false)]
+			bool disposeConsumer)
+		{
+			base.TestCreateAndDisposeWithConsumer(disposeConsumer, DEFAULT_TEST_QUEUE);
+		}
+	
+		[Test]
+		public void TestCreateAndDisposeWithProducer(
+			[Values(true, false)]
+			bool disposeProducer)
+		{
+			base.TestCreateAndDisposeWithProducer(disposeProducer, DEFAULT_TEST_QUEUE);
+		}
+	
+		[Test]
+		public void TestStartAfterSend(
+			[Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestStartAfterSend(deliveryMode, testDestRef);
+		}
+
+		/// <summary>
+		/// Tests if the consumer receives the messages that were sent before the
+		/// connection was started.
+		/// </summary>
+		[Test]
+		public override void TestStoppedConsumerHoldsMessagesTillStarted(
+			[Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef)
+		{
+			base.TestStoppedConsumerHoldsMessagesTillStarted(testDestRef);
+		}
+	
+		/// <summary>
+		/// Tests if the consumer is able to receive messages even when the
+		/// connecction restarts multiple times.
+		/// </summary>
+		[Test]
+        public override void TestMultipleConnectionStops(
+			[Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef)
+		{
+			base.TestMultipleConnectionStops(testDestRef);
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQConsumerTest.cs b/src/test/csharp/MSMQConsumerTest.cs
new file mode 100644
index 0000000..b7f7478
--- /dev/null
+++ b/src/test/csharp/MSMQConsumerTest.cs
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Threading;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQConsumerTest : ConsumerTest
+	{
+		protected const string DEFAULT_TEST_QUEUE = "transactionTestQueue";
+		protected const string DEFAULT_TEST_TOPIC = "defaultTestTopic";
+
+		public MSMQConsumerTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+// The .NET CF does not have the ability to interrupt threads, so this test is impossible.
+#if !NETCF
+		[Test]
+		public override void TestNoTimeoutConsumer(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+				AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			base.TestNoTimeoutConsumer(testDestRef, ackMode);
+		}
+
+		[Test]
+		public override void TestSyncReceiveConsumerClose(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+				AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			base.TestSyncReceiveConsumerClose(testDestRef, ackMode);
+		}
+
+		[Test]
+		public override void TestDoChangeSentMessage(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+				AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode,
+			[Values(true, false)] bool doClear)
+		{
+			base.TestDoChangeSentMessage(testDestRef, ackMode, doClear);
+		}
+
+		[Test]
+		public override void TestConsumerReceiveBeforeMessageDispatched(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+				AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			base.TestConsumerReceiveBeforeMessageDispatched(testDestRef, ackMode);
+		}
+
+		[Test]
+		public override void TestDontStart(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestDontStart(testDestRef, deliveryMode);
+		}
+
+		[Test]
+		public override void TestSendReceiveTransacted(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC, DEFAULT_TEST_TEMP_QUEUE, DEFAULT_TEST_TEMP_TOPIC*/)]
+            string testDestRef,
+			[Values(MsgDeliveryMode.NonPersistent, MsgDeliveryMode.Persistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveTransacted(testDestRef, deliveryMode);
+		}
+
+		[Test]
+		public void TestAckedMessageAreConsumed()
+		{
+			base.TestAckedMessageAreConsumed(DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public void TestLastMessageAcked()
+		{
+			base.TestLastMessageAcked(DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public void TestUnAckedMessageAreNotConsumedOnSessionClose()
+		{
+			base.TestUnAckedMessageAreNotConsumedOnSessionClose(DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public void TestAsyncAckedMessageAreConsumed()
+		{
+			base.TestAsyncAckedMessageAreConsumed(DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public void TestAsyncUnAckedMessageAreNotConsumedOnSessionClose()
+		{
+			base.TestAsyncUnAckedMessageAreNotConsumedOnSessionClose(DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public /*override*/ void TestAddRemoveAsnycMessageListener()
+		{
+			base.TestAddRemoveAsnycMessageListener(DestinationType.Queue, DEFAULT_TEST_QUEUE);
+		}
+
+		[Test]
+		public override void TestReceiveNoWait(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+				AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode,
+			[Values(MsgDeliveryMode.NonPersistent, MsgDeliveryMode.Persistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestReceiveNoWait(testDestRef, ackMode, deliveryMode);
+		}
+
+#endif
+
+    }
+}
diff --git a/src/test/csharp/MSMQDurableTest.cs b/src/test/csharp/MSMQDurableTest.cs
new file mode 100644
index 0000000..fe1d5b5
--- /dev/null
+++ b/src/test/csharp/MSMQDurableTest.cs
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+    [Ignore("Topics are not supported")]
+	public class MSMQDurableTest : DurableTest
+	{
+		protected const string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+		protected const string DEFAULT_TEST_TOPIC = "defaultTestTopic";
+		protected const string DURABLE_TEST_TOPIC = "durableConsumerTestTopic";
+
+		public MSMQDurableTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+		
+		[SetUp]
+		public override void SetUp()
+		{
+			base.SetUp();
+		}
+
+		[Test]
+		public void TestSendWhileClosed(
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+				AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			base.TestSendWhileClosed(ackMode, DEFAULT_TEST_TOPIC);
+	    }		
+		
+		[Test]
+		public void TestDurableConsumerSelectorChange(
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+				AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			base.TestDurableConsumerSelectorChange(ackMode, DEFAULT_TEST_TOPIC);
+		}
+
+		[Test]
+		public void TestDurableConsumer(
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge,
+				AcknowledgementMode.DupsOkAcknowledge, AcknowledgementMode.Transactional)]
+			AcknowledgementMode ackMode)
+		{
+			string testDurableTopicURI = GetDestinationURI(DURABLE_TEST_TOPIC);
+
+			base.TestDurableConsumer(ackMode, testDurableTopicURI); 
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQForeignMessageTransformationTest.cs b/src/test/csharp/MSMQForeignMessageTransformationTest.cs
new file mode 100644
index 0000000..17043f3
--- /dev/null
+++ b/src/test/csharp/MSMQForeignMessageTransformationTest.cs
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+    [TestFixture]
+    public class MSMQForeignMessageTransformationTest : ForeignMessageTransformationTest
+    {
+		protected const string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+		protected const string DEFAULT_TEST_TOPIC = "defaultTestTopic";
+
+		public MSMQForeignMessageTransformationTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		public override void TestSendReceiveForeignMessage(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveForeignMessage(testDestRef, deliveryMode);
+		}
+
+		[Test]
+		public override void TestSendReceiveForeignTextMessage(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveForeignTextMessage(testDestRef, deliveryMode);
+		}
+
+		[Test]
+		public override void TestSendReceiveForeignBytesMessage(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveForeignBytesMessage(testDestRef, deliveryMode);
+		}
+
+		[Test]
+		public override void TestSendReceiveForeignMapMessage(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveForeignMapMessage(testDestRef, deliveryMode);
+		}
+
+		[Test]
+		public override void TestSendReceiveForeignStreamMessage(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC*/)]
+            string testDestRef,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveForeignStreamMessage(testDestRef, deliveryMode);
+		}
+	}
+}
+
diff --git a/src/test/csharp/MSMQMapMessageTest.cs b/src/test/csharp/MSMQMapMessageTest.cs
new file mode 100644
index 0000000..3afbcbe
--- /dev/null
+++ b/src/test/csharp/MSMQMapMessageTest.cs
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+    [TestFixture]
+    public class MSMQMapMessageTest : MapMessageTest
+    {
+		protected static string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+
+		public MSMQMapMessageTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+        [Test]
+        public void TestSendReceiveMapMessage(
+            [Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+            MsgDeliveryMode deliveryMode)
+        {
+            base.TestSendReceiveMapMessage(deliveryMode, DEFAULT_TEST_QUEUE);
+        }
+
+        [Test]
+        public void TestSendReceiveNestedMapMessage(
+            [Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+            MsgDeliveryMode deliveryMode)
+        {
+            base.TestSendReceiveNestedMapMessage(deliveryMode, DEFAULT_TEST_QUEUE);
+        }
+    }
+}
diff --git a/src/test/csharp/MSMQMessageSelectorTest.cs b/src/test/csharp/MSMQMessageSelectorTest.cs
new file mode 100644
index 0000000..5a108cd
--- /dev/null
+++ b/src/test/csharp/MSMQMessageSelectorTest.cs
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using Apache.NMS.Test;
+using NUnit.Framework;
+using System.Globalization;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	[Category("LongRunning")]
+	public class MSMQMessageSelectorTest : MessageSelectorTest
+	{
+		protected const string SELECTOR_TEST_QUEUE = "messageSelectorTestQueue";
+		protected const string SELECTOR_TEST_TOPIC = "messageSelectorTestTopic";
+
+		public MSMQMessageSelectorTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		public override void TestFilterIgnoredMessages(
+			[Values(SELECTOR_TEST_QUEUE /*, SELECTOR_TEST_TOPIC*/)]
+			string testDestRef)
+		{
+			base.TestFilterIgnoredMessages(testDestRef);
+		}
+
+		[Test]
+		public override void TestFilterIgnoredMessagesSlowConsumer(
+			[Values(SELECTOR_TEST_QUEUE /*, SELECTOR_TEST_TOPIC*/)]
+			string testDestRef)
+		{
+			base.TestFilterIgnoredMessagesSlowConsumer(testDestRef);
+		}
+
+
+		[Test]
+		public override void TestInvalidSelector(
+			[Values(SELECTOR_TEST_QUEUE)]
+			string testDestRef)
+		{
+			base.TestInvalidSelector(testDestRef);
+		}
+
+		[Test]
+		public void TestSelectByMessageId(
+			[Values(SELECTOR_TEST_QUEUE)]
+			string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession())
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+
+                    using(IMessageProducer producer = session.CreateProducer(destination))
+                    {
+                        ITextMessage message = null;
+
+                        int COUNT = 5;
+                        for(int i = 1; i <= COUNT; i++)
+                        {
+                            message = session.CreateTextMessage("MessageSelectorTest - TestSelectByMessageId: " + i.ToString());
+                            producer.Send(message);
+                        }
+
+					    using(IQueueBrowser browser = session.CreateBrowser((IQueue)destination))
+					    {
+                            int i = 0;
+                            foreach(IMessage message0 in browser)
+                            {
+                                if(++i == COUNT / 2)
+                                {
+                                    message = message0 as ITextMessage;
+                                    break;
+                                }
+                            }
+						}
+
+                        string selector = "NMSMessageId = '" + message.NMSMessageId + "'";
+
+					    using(IMessageConsumer consumer = session.CreateConsumer(destination, selector))
+					    {
+							ITextMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)) as ITextMessage;
+							Assert.IsNotNull(msg);
+							Assert.AreEqual(msg.Text, message.Text);
+							Assert.AreEqual(msg.NMSMessageId, message.NMSMessageId);
+
+							msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)) as ITextMessage;
+							Assert.IsNull(msg);
+						}
+					}
+				}
+			}
+		}
+
+		[Test]
+		public void TestSelectByLookupId(
+			[Values(SELECTOR_TEST_QUEUE)]
+			string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession())
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+
+                    using(IMessageProducer producer = session.CreateProducer(destination))
+                    {
+                        ITextMessage message = null;
+
+                        int COUNT = 5;
+                        for(int i = 1; i <= COUNT; i++)
+                        {
+                            message = session.CreateTextMessage("MessageSelectorTest - TestSelectByLookupId: " + i.ToString());
+                            producer.Send(message);
+                        }
+
+					    using(IQueueBrowser browser = session.CreateBrowser((IQueue)destination))
+					    {
+                            int i = 0;
+                            foreach(IMessage message0 in browser)
+                            {
+                                if(++i == COUNT / 2)
+                                {
+                                    message = message0 as ITextMessage;
+                                    break;
+                                }
+                            }
+						}
+
+                        long lookupId = (long)(message.Properties["LookupId"]);
+                        string selector = "LookupId = " + lookupId.ToString(CultureInfo.InvariantCulture);
+
+					    using(IMessageConsumer consumer = session.CreateConsumer(destination, selector))
+					    {
+							ITextMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)) as ITextMessage;
+							Assert.IsNotNull(msg);
+							Assert.AreEqual(msg.Text, message.Text);
+							Assert.AreEqual(msg.Properties["LookupId"], lookupId);
+
+							msg = consumer.Receive(TimeSpan.FromMilliseconds(2000)) as ITextMessage;
+							Assert.IsNull(msg);
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQMessageTest.cs b/src/test/csharp/MSMQMessageTest.cs
new file mode 100644
index 0000000..1cfcd70
--- /dev/null
+++ b/src/test/csharp/MSMQMessageTest.cs
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQMessageTest : MessageTest
+	{
+		protected static string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+
+		public MSMQMessageTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		public void TestSendReceiveMessageProperties(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveMessageProperties(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+	}
+}
+
diff --git a/src/test/csharp/MSMQMessageTransformerTest.cs b/src/test/csharp/MSMQMessageTransformerTest.cs
new file mode 100644
index 0000000..2249db5
--- /dev/null
+++ b/src/test/csharp/MSMQMessageTransformerTest.cs
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQMessageTransformerTest : MessageTransformerTest
+	{
+		public MSMQMessageTransformerTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+				
+		[Test]
+		public override void TestProducerTransformer(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestProducerTransformer(deliveryMode);
+		}
+		
+		[Test]
+		public override void TestConsumerTransformer(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestConsumerTransformer(deliveryMode);
+		}
+	}
+}
+
diff --git a/src/test/csharp/MSMQNMSPropertyTest.cs b/src/test/csharp/MSMQNMSPropertyTest.cs
new file mode 100644
index 0000000..3968aea
--- /dev/null
+++ b/src/test/csharp/MSMQNMSPropertyTest.cs
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQNMSPropertyTest : NMSPropertyTest
+	{
+		protected static string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+
+		public MSMQNMSPropertyTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		public void TestSendReceiveNMSProperties(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveNMSProperties(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQProducerTest.cs b/src/test/csharp/MSMQProducerTest.cs
new file mode 100644
index 0000000..bbe86fd
--- /dev/null
+++ b/src/test/csharp/MSMQProducerTest.cs
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQProducerTest : ProducerTest
+	{
+		protected const string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+		protected const string DEFAULT_TEST_TOPIC = "defaultTestTopic";
+		protected const string DEFAULT_TEST_TEMP_QUEUE = "defaultTestTempQueue";
+		protected const string DEFAULT_TEST_TEMP_TOPIC = "defaultTestTempTopic";
+
+		protected const string DEFAULT_TEST_QUEUE2 = "defaultTestQueue2";
+		protected const string DEFAULT_TEST_TOPIC2 = "defaultTestTopic2";
+		protected const string DEFAULT_TEST_TEMP_QUEUE2 = "defaultTestTempQueue2";
+		protected const string DEFAULT_TEST_TEMP_TOPIC2 = "defaultTestTempTopic2";
+
+		public MSMQProducerTest()
+			: base(new NMSTestSupport())
+		{
+		}
+
+        [Test]
+        public override void TestProducerSendToNullDestinationWithoutDefault()
+        {
+            base.TestProducerSendToNullDestinationWithoutDefault();
+        }
+
+        [Test]
+        public override void TestProducerSendToNullDestinationWithDefault(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC, DEFAULT_TEST_TEMP_QUEUE, DEFAULT_TEST_TEMP_TOPIC*/)]
+            string testDestRef)
+        {
+            base.TestProducerSendToNullDestinationWithDefault(testDestRef);
+        }
+
+		[Test]
+		public override void TestProducerSendToNonDefaultDestination(
+            [Values(DEFAULT_TEST_QUEUE /*, DEFAULT_TEST_TOPIC, DEFAULT_TEST_TEMP_QUEUE, DEFAULT_TEST_TEMP_TOPIC*/)]
+            string unusedTestDestRef,
+            [Values(DEFAULT_TEST_QUEUE2 /*, DEFAULT_TEST_TOPIC2, DEFAULT_TEST_TEMP_QUEUE2, DEFAULT_TEST_TEMP_TOPIC2*/)]
+            string usedTestDestRef)
+		{
+            base.TestProducerSendToNonDefaultDestination(unusedTestDestRef, usedTestDestRef);
+        }
+	}
+}
diff --git a/src/test/csharp/MSMQRequestResponseTest.cs b/src/test/csharp/MSMQRequestResponseTest.cs
new file mode 100644
index 0000000..1261ab1
--- /dev/null
+++ b/src/test/csharp/MSMQRequestResponseTest.cs
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQRequestResponseTest : RequestResponseTest
+	{
+		protected const string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+		protected const string DEFAULT_TEST_QUEUE2 = "defaultTestQueue2";
+
+		public MSMQRequestResponseTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		[Category("RequestResponse")]		
+		public void TestRequestResponseMessaging()
+		{
+			base.TestRequestResponseMessaging(DEFAULT_TEST_QUEUE, DEFAULT_TEST_QUEUE2);
+		}
+	}
+}
+
diff --git a/src/test/csharp/MSMQStreamMessageTest.cs b/src/test/csharp/MSMQStreamMessageTest.cs
new file mode 100644
index 0000000..75d8c99
--- /dev/null
+++ b/src/test/csharp/MSMQStreamMessageTest.cs
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQStreamMessageTest : StreamMessageTest
+	{
+		protected static string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+
+		public MSMQStreamMessageTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		public void TestSendReceiveStreamMessage(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveStreamMessage(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQTempDestinationDeletionTest.cs b/src/test/csharp/MSMQTempDestinationDeletionTest.cs
new file mode 100644
index 0000000..b2d8a41
--- /dev/null
+++ b/src/test/csharp/MSMQTempDestinationDeletionTest.cs
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+    [Ignore("Temporary queues are not supported")]
+	public class MSMQTempDestinationDeletionTest : TempDestinationDeletionTest
+	{
+		protected const string DELETION_TEST_QUEUE = "deletionTestQueue";
+		protected const string DELETION_TEST_TOPIC = "deletionTestTopic";
+		protected const string DELETION_TEST_TEMP_QUEUE = "deletionTestTempQueue";
+		protected const string DELETION_TEST_TEMP_TOPIC = "deletionTestTempTopic";
+
+		public MSMQTempDestinationDeletionTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		public override void TestTempDestinationDeletion(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode,
+			[Values(DELETION_TEST_QUEUE, DELETION_TEST_TOPIC, DELETION_TEST_TEMP_QUEUE, DELETION_TEST_TEMP_TOPIC)]
+			string testDestRef)
+		{
+			base.TestTempDestinationDeletion(deliveryMode, testDestRef);
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQTempDestinationTest.cs b/src/test/csharp/MSMQTempDestinationTest.cs
new file mode 100644
index 0000000..de62683
--- /dev/null
+++ b/src/test/csharp/MSMQTempDestinationTest.cs
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+    [TestFixture]
+    [Ignore("Temporary queues are not supported")]
+    public class MSMQTempDestinationTest : TempDestinationTest
+    {
+		public MSMQTempDestinationTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+        [SetUp]
+        public override void SetUp()
+        {
+            base.SetUp();
+        }
+
+        [TearDown]
+        public override void TearDown()
+        {
+            base.TearDown();
+        }
+
+        [Test]
+        public override void TestTempDestOnlyConsumedByLocalConn()
+        {
+            base.TestTempDestOnlyConsumedByLocalConn();
+        }
+
+        [Test]
+        public override void TestTempQueueHoldsMessagesWithConsumers()
+        {
+            base.TestTempQueueHoldsMessagesWithConsumers();
+        }
+
+        [Test]
+        public override void TestTempQueueHoldsMessagesWithoutConsumers()
+        {
+            base.TestTempQueueHoldsMessagesWithoutConsumers();
+        }
+
+        [Test]
+        public override void TestTmpQueueWorksUnderLoad()
+        {
+            base.TestTmpQueueWorksUnderLoad();
+        }
+    }
+}
diff --git a/src/test/csharp/MSMQTestSupport.cs b/src/test/csharp/MSMQTestSupport.cs
new file mode 100644
index 0000000..13725a8
--- /dev/null
+++ b/src/test/csharp/MSMQTestSupport.cs
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Xml;
+using Apache.NMS.Test;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+using Apache.NMS.MSMQ;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	/// <summary>
+	/// Useful class for test cases support.
+	/// </summary>
+	public class MSMQTestSupport : NMSTestSupport
+	{
+		/// <summary>
+		/// Gets the environment variable name for the configuration file path.
+		/// </summary>
+		/// <returns>Environment variable name</returns>
+		public override string GetConfigEnvVarName()
+		{
+			return "MSMQTESTCONFIGPATH";
+		}
+
+		/// <summary>
+		/// Gets the default name for the configuration filename.
+		/// </summary>
+		/// <returns>Default name of the configuration filename</returns>
+		public override string GetDefaultConfigFileName()
+		{
+			return "msmqprovider-test.config";
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQTextMessageTest.cs b/src/test/csharp/MSMQTextMessageTest.cs
new file mode 100644
index 0000000..dfbd061
--- /dev/null
+++ b/src/test/csharp/MSMQTextMessageTest.cs
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQTextMessageTest : TextMessageTest
+	{
+		protected static string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+
+		public MSMQTextMessageTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+		[Test]
+		public void TestSendReceiveTextMessage(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			base.TestSendReceiveTextMessage(deliveryMode, DEFAULT_TEST_QUEUE);
+		}
+	}
+}
diff --git a/src/test/csharp/MSMQTransactionTest.cs b/src/test/csharp/MSMQTransactionTest.cs
new file mode 100644
index 0000000..c269d0c
--- /dev/null
+++ b/src/test/csharp/MSMQTransactionTest.cs
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+    [TestFixture]
+    public class MSMQTransactionTest : TransactionTest
+    {
+        protected static string TRANSACTION_TEST_QUEUE = "transactionTestQueue";
+
+		public MSMQTransactionTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+        [Test]
+        public void TestSendRollback(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+        {
+            base.TestSendRollback(deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+
+        [Test]
+        public void TestSendSessionClose(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+        {
+            base.TestSendSessionClose(deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+
+        [Test]
+        public void TestReceiveRollback(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+        {
+            base.TestReceiveRollback(deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+
+
+        [Test]
+        public void TestReceiveTwoThenRollback(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+        {
+            base.TestReceiveTwoThenRollback(deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+
+        [Test]
+        public void TestSendCommitNonTransaction(
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge)]
+			AcknowledgementMode ackMode,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+        {
+            base.TestSendCommitNonTransaction(ackMode, deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+
+        [Test]
+        public void TestReceiveCommitNonTransaction(
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge)]
+			AcknowledgementMode ackMode,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+            base.TestReceiveCommitNonTransaction(ackMode, deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+
+        [Test]
+        public void TestReceiveRollbackNonTransaction(
+			[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge)]
+			AcknowledgementMode ackMode,
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+            base.TestReceiveRollbackNonTransaction(ackMode, deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+
+        [Test]
+        public void TestRedispatchOfRolledbackTx(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+        {
+            base.TestRedispatchOfRolledbackTx(deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+
+        [Test]
+        public void TestRedispatchOfUncommittedTx(
+			[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+        {
+            base.TestRedispatchOfUncommittedTx(deliveryMode, TRANSACTION_TEST_QUEUE);
+        }
+    }
+}
+
+
diff --git a/src/test/csharp/MSMQXmlMessageTest.cs b/src/test/csharp/MSMQXmlMessageTest.cs
new file mode 100644
index 0000000..757e1f9
--- /dev/null
+++ b/src/test/csharp/MSMQXmlMessageTest.cs
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Test;
+using NUnit.Framework;
+
+namespace Apache.NMS.MSMQ.Test
+{
+	[TestFixture]
+	public class MSMQXmlMessageTest : XmlMessageTest
+	{
+		protected static string DEFAULT_TEST_QUEUE = "defaultTestQueue";
+
+		public MSMQXmlMessageTest()
+			: base(new MSMQTestSupport())
+		{
+		}
+
+#if NET_3_5 || MONO
+
+		[Test]
+		public void TestSendReceiveXmlMessage_Net35()
+		{
+			base.TestSendReceiveXmlMessage_Net35(DEFAULT_TEST_QUEUE);
+		}
+
+#else
+
+		// Test the obsolete API versions until they are completely removed.
+		[Test]
+		public void SendReceiveXmlMessage()
+		{
+			base.TestSendReceiveXmlMessage(DEFAULT_TEST_QUEUE);
+		}
+
+#endif
+	}
+}
diff --git a/src/test/csharp/MapMessageTest.cs b/src/test/csharp/MapMessageTest.cs
new file mode 100644
index 0000000..f904c97
--- /dev/null
+++ b/src/test/csharp/MapMessageTest.cs
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class MapMessageTest : NMSTest
+	{
+		protected bool a = true;
+		protected byte b = 123;
+		protected char c = 'c';
+		protected short d = 0x1234;
+		protected int e = 0x12345678;
+		protected long f = 0x1234567812345678;
+		protected string g = "Hello World!";
+		protected bool h = false;
+		protected byte i = 0xFF;
+		protected short j = -0x1234;
+		protected int k = -0x12345678;
+		protected long l = -0x1234567812345678;
+		protected float m = 2.1F;
+		protected double n = 2.3;
+		protected byte[] o = {1, 2, 3, 4, 5};
+
+		protected MapMessageTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void TestSendReceiveMapMessage(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						IMapMessage request = session.CreateMapMessage();
+						request.Body["a"] = a;
+						request.Body["b"] = b;
+						request.Body["c"] = c;
+						request.Body["d"] = d;
+						request.Body["e"] = e;
+						request.Body["f"] = f;
+						request.Body["g"] = g;
+						request.Body["h"] = h;
+						request.Body["i"] = i;
+						request.Body["j"] = j;
+						request.Body["k"] = k;
+						request.Body["l"] = l;
+						request.Body["m"] = m;
+						request.Body["n"] = n;
+						request.Body["o"] = o;
+						producer.Send(request);
+
+						IMapMessage message = consumer.Receive(receiveTimeout) as IMapMessage;
+						Assert.IsNotNull(message, "No message returned!");
+						Assert.AreEqual(request.Body.Count, message.Body.Count, "Invalid number of message maps.");
+						Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+						Assert.AreEqual(ToHex(f), ToHex(message.Body.GetLong("f")), "map entry: f as hex");
+
+						// use generic API to access entries
+						Assert.AreEqual(a, message.Body["a"], "generic map entry: a");
+						Assert.AreEqual(b, message.Body["b"], "generic map entry: b");
+						Assert.AreEqual(c, message.Body["c"], "generic map entry: c");
+						Assert.AreEqual(d, message.Body["d"], "generic map entry: d");
+						Assert.AreEqual(e, message.Body["e"], "generic map entry: e");
+						Assert.AreEqual(f, message.Body["f"], "generic map entry: f");
+						Assert.AreEqual(g, message.Body["g"], "generic map entry: g");
+						Assert.AreEqual(h, message.Body["h"], "generic map entry: h");
+						Assert.AreEqual(i, message.Body["i"], "generic map entry: i");
+						Assert.AreEqual(j, message.Body["j"], "generic map entry: j");
+						Assert.AreEqual(k, message.Body["k"], "generic map entry: k");
+						Assert.AreEqual(l, message.Body["l"], "generic map entry: l");
+						Assert.AreEqual(m, message.Body["m"], "generic map entry: m");
+						Assert.AreEqual(n, message.Body["n"], "generic map entry: n");
+						Assert.AreEqual(o, message.Body["o"], "generic map entry: o");
+
+						// use type safe APIs
+						Assert.AreEqual(a, message.Body.GetBool("a"), "map entry: a");
+						Assert.AreEqual(b, message.Body.GetByte("b"), "map entry: b");
+						Assert.AreEqual(c, message.Body.GetChar("c"), "map entry: c");
+						Assert.AreEqual(d, message.Body.GetShort("d"), "map entry: d");
+						Assert.AreEqual(e, message.Body.GetInt("e"), "map entry: e");
+						Assert.AreEqual(f, message.Body.GetLong("f"), "map entry: f");
+						Assert.AreEqual(g, message.Body.GetString("g"), "map entry: g");
+						Assert.AreEqual(h, message.Body.GetBool("h"), "map entry: h");
+						Assert.AreEqual(i, message.Body.GetByte("i"), "map entry: i");
+						Assert.AreEqual(j, message.Body.GetShort("j"), "map entry: j");
+						Assert.AreEqual(k, message.Body.GetInt("k"), "map entry: k");
+						Assert.AreEqual(l, message.Body.GetLong("l"), "map entry: l");
+						Assert.AreEqual(m, message.Body.GetFloat("m"), "map entry: m");
+						Assert.AreEqual(n, message.Body.GetDouble("n"), "map entry: n");
+						Assert.AreEqual(o, message.Body.GetBytes("o"), "map entry: o");
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestSendReceiveNestedMapMessage(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						try
+						{
+							producer.DeliveryMode = deliveryMode;
+							IMapMessage request = session.CreateMapMessage();
+							const string textFieldValue = "Nested Map Messages Rule!";
+
+							request.Body.SetString("textField", textFieldValue);
+
+							IDictionary grandChildMap = new Hashtable();
+							grandChildMap["x"] = "abc";
+							grandChildMap["y"] = new ArrayList(new object[] { "a", "b", "c" });
+
+							IDictionary nestedMap = new Hashtable();
+							nestedMap["a"] = "foo";
+							nestedMap["b"] = (int) 23;
+							nestedMap["c"] = (long) 45;
+							nestedMap["d"] = grandChildMap;
+
+							request.Body.SetDictionary("mapField", nestedMap);
+							request.Body.SetList("listField", new ArrayList(new Object[] { "a", "b", "c" }));
+
+							producer.Send(request);
+
+							IMapMessage message = consumer.Receive(receiveTimeout) as IMapMessage;
+							Assert.IsNotNull(message, "No message returned!");
+							Assert.AreEqual(request.Body.Count, message.Body.Count, "Invalid number of message maps.");
+							Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+							string textFieldResponse = message.Body.GetString("textField");
+							Assert.AreEqual(textFieldValue, textFieldResponse, "textField does not match.");
+
+							IDictionary nestedMapResponse = message.Body.GetDictionary("mapField");
+							Assert.IsNotNull(nestedMapResponse, "Nested map not returned.");
+							Assert.AreEqual(nestedMap.Count, nestedMapResponse.Count, "nestedMap: Wrong number of elements");
+							Assert.AreEqual("foo", nestedMapResponse["a"], "nestedMap: a");
+							Assert.AreEqual(23, nestedMapResponse["b"], "nestedMap: b");
+							Assert.AreEqual(45, nestedMapResponse["c"], "nestedMap: c");
+
+							IDictionary grandChildMapResponse = nestedMapResponse["d"] as IDictionary;
+							Assert.IsNotNull(grandChildMapResponse, "Grand child map not returned.");
+							Assert.AreEqual(grandChildMap.Count, grandChildMapResponse.Count, "grandChildMap: Wrong number of elements");
+							Assert.AreEqual(grandChildMapResponse["x"], "abc", "grandChildMap: x");
+
+							IList grandChildList = grandChildMapResponse["y"] as IList;
+							Assert.IsNotNull(grandChildList, "Grand child list not returned.");
+							Assert.AreEqual(3, grandChildList.Count, "grandChildList: Wrong number of list elements.");
+							Assert.AreEqual("a", grandChildList[0], "grandChildList: a");
+							Assert.AreEqual("b", grandChildList[1], "grandChildList: b");
+							Assert.AreEqual("c", grandChildList[2], "grandChildList: c");
+
+							IList listFieldResponse = message.Body.GetList("listField");
+							Assert.IsNotNull(listFieldResponse, "Nested list not returned.");
+							Assert.AreEqual(3, listFieldResponse.Count, "listFieldResponse: Wrong number of list elements.");
+							Assert.AreEqual("a", listFieldResponse[0], "listFieldResponse: a");
+							Assert.AreEqual("b", listFieldResponse[1], "listFieldResponse: b");
+							Assert.AreEqual("c", listFieldResponse[2], "listFieldResponse: c");
+						}
+						catch(NotSupportedException)
+						{
+						}
+						catch(NMSException e)
+						{
+							Assert.IsTrue(e.InnerException.GetType() == typeof(NotSupportedException));
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/test/csharp/MessageSelectorTest.cs b/src/test/csharp/MessageSelectorTest.cs
new file mode 100644
index 0000000..413a965
--- /dev/null
+++ b/src/test/csharp/MessageSelectorTest.cs
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Threading;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	//[Category("LongRunning")]
+	public class MessageSelectorTest : NMSTest
+	{
+		private int receivedNonIgnoredMsgCount = 0;
+		private int receivedIgnoredMsgCount = 0;
+		private bool simulateSlowConsumer = false;
+
+		protected MessageSelectorTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void TestFilterIgnoredMessages(
+			//[Values(SELECTOR_TEST_QUEUE, SELECTOR_TEST_TOPIC)]
+			string testDestRef)
+		{
+			simulateSlowConsumer = false;
+			RunFilterIgnoredMessagesTest(testDestRef);
+		}
+
+		/// <summary>
+		/// A slow consumer will trigger the producer flow control on the broker when the destination is
+		/// a queue.  It will also trigger the consumer flow control by slowing down the feed to all of the
+		/// consumers on the queue to only send messages as fast as the slowest consumer can run.
+		/// When sending to a topic, the producer will not be slowed down, and consumers will be allowed
+		/// to run as fast as they can go.
+		/// Since this test can take a long time to run, it is marked as explicit.
+		/// </summary>
+		/// <param name="testDestRef"></param>
+		//[Test]
+		public virtual void TestFilterIgnoredMessagesSlowConsumer(
+			//[Values(SELECTOR_TEST_QUEUE, SELECTOR_TEST_TOPIC)]
+			string testDestRef)
+		{
+			simulateSlowConsumer = true;
+			RunFilterIgnoredMessagesTest(testDestRef);
+		}
+
+		public void RunFilterIgnoredMessagesTest(string testDestRef)
+		{
+			TimeSpan ttl = TimeSpan.FromMinutes(30);
+			const int MaxNumRequests = 100000;
+
+			using(IConnection connection1 = CreateConnection(GetTestClientId()))
+			using(IConnection connection2 = CreateConnection(GetTestClientId()))
+			using(IConnection connection3 = CreateConnection(GetTestClientId()))
+			{
+				connection1.Start();
+				connection2.Start();
+				connection3.Start();
+				using(ISession session1 = connection1.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				using(ISession session2 = connection2.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				using(ISession session3 = connection3.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination1 = GetClearDestinationByNodeReference(session1, testDestRef);
+					IDestination destination2 = GetClearDestinationByNodeReference(session2, testDestRef);
+					IDestination destination3 = GetClearDestinationByNodeReference(session3, testDestRef);
+
+					using(IMessageProducer producer = session1.CreateProducer(destination1))
+					using(IMessageConsumer consumer1 = session2.CreateConsumer(destination2, "JMSType NOT LIKE '%IGNORE'"))
+					{
+						int numNonIgnoredMsgsSent = 0;
+						int numIgnoredMsgsSent = 0;
+
+						producer.DeliveryMode = MsgDeliveryMode.NonPersistent;
+
+						receivedNonIgnoredMsgCount = 0;
+						receivedIgnoredMsgCount = 0;
+						consumer1.Listener += new MessageListener(OnNonIgnoredMessage);
+						IMessageConsumer consumer2 = null;
+
+						for(int index = 1; index <= MaxNumRequests; index++)
+						{
+							IMessage request = session1.CreateTextMessage(String.Format("Hello World! [{0} of {1}]", index, MaxNumRequests));
+
+							request.NMSTimeToLive = ttl;
+							if(0 == (index % 2))
+							{
+								request.NMSType = "ACTIVE";
+								numNonIgnoredMsgsSent++;
+							}
+							else
+							{
+								request.NMSType = "ACTIVE.IGNORE";
+								numIgnoredMsgsSent++;
+							}
+
+if(index % 200 == 0) Console.WriteLine("{0} Sending message {1}/{2}", DateTime.Now, index, MaxNumRequests);
+							producer.Send(request);
+
+							if(2000 == index)
+							{
+								// Start the second consumer
+								if(destination3.IsTopic)
+								{
+									// Reset the ignored message sent count, since all previous messages
+									// will not have been consumed on a topic.
+									numIgnoredMsgsSent = 0;
+								}
+
+								consumer2 = session3.CreateConsumer(destination3, "JMSType LIKE '%IGNORE'");
+								consumer2.Listener += new MessageListener(OnIgnoredMessage);
+							}
+						}
+
+						// Create a waiting loop that will coordinate the end of the test.  It checks
+						// to see that all intended messages were received.  It will continue to wait as
+						// long as new messages are being received.  If it stops receiving messages before
+						// it receives everything it expects, it will eventually timeout and the test will fail.
+						int waitCount = 0;
+						int lastReceivedINongnoredMsgCount = receivedNonIgnoredMsgCount;
+						int lastReceivedIgnoredMsgCount = receivedIgnoredMsgCount;
+
+						while(receivedNonIgnoredMsgCount < numNonIgnoredMsgsSent
+								|| receivedIgnoredMsgCount < numIgnoredMsgsSent)
+						{
+							if(lastReceivedINongnoredMsgCount != receivedNonIgnoredMsgCount
+								|| lastReceivedIgnoredMsgCount != receivedIgnoredMsgCount)
+							{
+								// Reset the wait count.
+								waitCount = 0;
+							}
+							else
+							{
+								waitCount++;
+							}
+
+							lastReceivedINongnoredMsgCount = receivedNonIgnoredMsgCount;
+							lastReceivedIgnoredMsgCount = receivedIgnoredMsgCount;
+
+							Assert.IsTrue(waitCount <= 30, String.Format("Timeout waiting for all messages to be delivered. Only {0} of {1} non-ignored messages delivered.  Only {2} of {3} ignored messages delivered.",
+								receivedNonIgnoredMsgCount, numNonIgnoredMsgsSent, receivedIgnoredMsgCount, numIgnoredMsgsSent));
+							Thread.Sleep(1000);
+						}
+
+						consumer2.Dispose();
+					}
+				}
+			}
+		}
+
+		protected void OnNonIgnoredMessage(IMessage message)
+		{
+			receivedNonIgnoredMsgCount++;
+			Assert.AreEqual(message.NMSType, "ACTIVE");
+if(receivedNonIgnoredMsgCount % 200 == 0) Console.WriteLine("{0} Received non ignored message {1}", DateTime.Now, receivedNonIgnoredMsgCount);
+		}
+
+		protected void OnIgnoredMessage(IMessage message)
+		{
+			receivedIgnoredMsgCount++;
+			Assert.AreEqual(message.NMSType, "ACTIVE.IGNORE");
+			if(simulateSlowConsumer)
+			{
+				// Simulate a slow consumer  It doesn't have to be too slow in a high speed environment
+				// in order to trigger producer flow control.
+				Thread.Sleep(10);
+			}
+if(receivedIgnoredMsgCount % 200 == 0) Console.WriteLine("{0} Received     ignored message {1}", DateTime.Now, receivedIgnoredMsgCount);
+		}
+
+		//[Test]
+		public virtual void TestInvalidSelector(
+			//[Values(SELECTOR_TEST_QUEUE)]
+			string testDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession())
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+
+                    string selector = "THIS IS NOT A VALID SELECTOR";
+
+                    try
+                    {
+					    using(IMessageConsumer consumer = session.CreateConsumer(destination, selector))
+					    {
+                            Assert.Fail("Consumer should have thrown an NotSupportedException");
+						}
+					}
+                    catch(InvalidSelectorException ex)
+                    {
+                    }
+                    catch(Exception ex)
+                    {
+                        Assert.Fail("Wrong Exception Type Thrown: " + ex.GetType().Name);
+                    }
+				}
+			}
+		}
+
+
+	}
+}
diff --git a/src/test/csharp/MessageTest.cs b/src/test/csharp/MessageTest.cs
new file mode 100644
index 0000000..6cfe45c
--- /dev/null
+++ b/src/test/csharp/MessageTest.cs
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class MessageTest : NMSTest
+	{
+		protected bool		a = true;
+		protected byte		b = 123;
+		protected char		c = 'c';
+		protected short		d = 0x1234;
+		protected int		e = 0x12345678;
+		protected long		f = 0x1234567812345678;
+		protected string	g = "Hello World!";
+		protected bool		h = false;
+		protected byte		i = 0xFF;
+		protected short		j = -0x1234;
+		protected int		k = -0x12345678;
+		protected long		l = -0x1234567812345678;
+		protected float		m = 2.1F;
+		protected double	n = 2.3;
+		protected byte[]    o = {1, 2, 3, 4, 5};
+
+		protected MessageTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void TestSendReceiveMessageProperties(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						IMessage request = session.CreateMessage();
+						request.Properties["a"] = a;
+						request.Properties["b"] = b;
+						request.Properties["c"] = c;
+						request.Properties["d"] = d;
+						request.Properties["e"] = e;
+						request.Properties["f"] = f;
+						request.Properties["g"] = g;
+						request.Properties["h"] = h;
+						request.Properties["i"] = i;
+						request.Properties["j"] = j;
+						request.Properties["k"] = k;
+						request.Properties["l"] = l;
+						request.Properties["m"] = m;
+						request.Properties["n"] = n;
+						
+						try
+						{
+							request.Properties["o"] = o;
+							Assert.Fail("Should not be able to add a Byte[] to the Properties of a Message.");
+						}
+						catch
+						{
+							// Expected
+						}
+						
+						try
+						{
+							request.Properties.SetBytes("o", o);
+							Assert.Fail("Should not be able to add a Byte[] to the Properties of a Message.");
+						}
+						catch
+						{
+							// Expected
+						}						
+						
+						producer.Send(request);
+
+						IMessage message = consumer.Receive(receiveTimeout);
+						Assert.IsNotNull(message, "No message returned!");
+						Assert.AreEqual(request.Properties.Count, message.Properties.Count, "Invalid number of properties.");
+						Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+						Assert.AreEqual(ToHex(f), ToHex(message.Properties.GetLong("f")), "map entry: f as hex");
+
+						// use generic API to access entries
+						// Perform a string only comparison here since some NMS providers are type limited and
+						// may return only a string instance from the generic [] accessor.  Each provider should
+						// further test this functionality to determine that the correct type is returned if
+						// it is capable of doing so.
+						Assert.AreEqual(a.ToString(), message.Properties["a"].ToString(), "generic map entry: a");
+						Assert.AreEqual(b.ToString(), message.Properties["b"].ToString(), "generic map entry: b");
+						Assert.AreEqual(c.ToString(), message.Properties["c"].ToString(), "generic map entry: c");
+						Assert.AreEqual(d.ToString(), message.Properties["d"].ToString(), "generic map entry: d");
+						Assert.AreEqual(e.ToString(), message.Properties["e"].ToString(), "generic map entry: e");
+						Assert.AreEqual(f.ToString(), message.Properties["f"].ToString(), "generic map entry: f");
+						Assert.AreEqual(g.ToString(), message.Properties["g"].ToString(), "generic map entry: g");
+						Assert.AreEqual(h.ToString(), message.Properties["h"].ToString(), "generic map entry: h");
+						Assert.AreEqual(i.ToString(), message.Properties["i"].ToString(), "generic map entry: i");
+						Assert.AreEqual(j.ToString(), message.Properties["j"].ToString(), "generic map entry: j");
+						Assert.AreEqual(k.ToString(), message.Properties["k"].ToString(), "generic map entry: k");
+						Assert.AreEqual(l.ToString(), message.Properties["l"].ToString(), "generic map entry: l");
+						Assert.AreEqual(m.ToString(), message.Properties["m"].ToString(), "generic map entry: m");
+						Assert.AreEqual(n.ToString(), message.Properties["n"].ToString(), "generic map entry: n");
+
+						// use type safe APIs
+						Assert.AreEqual(a, message.Properties.GetBool("a"),   "map entry: a");
+						Assert.AreEqual(b, message.Properties.GetByte("b"),   "map entry: b");
+						Assert.AreEqual(c, message.Properties.GetChar("c"),   "map entry: c");
+						Assert.AreEqual(d, message.Properties.GetShort("d"),  "map entry: d");
+						Assert.AreEqual(e, message.Properties.GetInt("e"),    "map entry: e");
+						Assert.AreEqual(f, message.Properties.GetLong("f"),   "map entry: f");
+						Assert.AreEqual(g, message.Properties.GetString("g"), "map entry: g");
+						Assert.AreEqual(h, message.Properties.GetBool("h"),   "map entry: h");
+						Assert.AreEqual(i, message.Properties.GetByte("i"),   "map entry: i");
+						Assert.AreEqual(j, message.Properties.GetShort("j"),  "map entry: j");
+						Assert.AreEqual(k, message.Properties.GetInt("k"),    "map entry: k");
+						Assert.AreEqual(l, message.Properties.GetLong("l"),   "map entry: l");
+						Assert.AreEqual(m, message.Properties.GetFloat("m"),  "map entry: m");
+						Assert.AreEqual(n, message.Properties.GetDouble("n"), "map entry: n");
+					}
+				}
+			}
+		}
+	}
+}
+
diff --git a/src/test/csharp/MessageTransformerTest.cs b/src/test/csharp/MessageTransformerTest.cs
new file mode 100644
index 0000000..d954fe7
--- /dev/null
+++ b/src/test/csharp/MessageTransformerTest.cs
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class MessageTransformerTest : NMSTest
+	{
+		private string propertyName = "ADDITIONAL-PROPERTY";
+		private string propertyValue = "ADDITIONAL-PROPERTY-VALUE";
+
+		protected MessageTransformerTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void TestProducerTransformer(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = session.CreateTemporaryTopic();
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						producer.ProducerTransformer = DoProducerTransform;
+
+                        IMessage message = session.CreateMessage();
+
+                        message.Properties["Test"] = "Value";
+
+                        producer.Send(message);
+
+                        message = consumer.Receive(TimeSpan.FromMilliseconds(5000));
+
+                        Assert.IsNotNull(message);
+                        Assert.IsTrue(message.Properties.Count == 2);
+
+                        Assert.AreEqual("Value", message.Properties["Test"]);
+                        Assert.AreEqual(propertyValue, message.Properties[propertyName]);
+					}
+				}
+			}
+		}
+		
+		//[Test]
+		public virtual void TestConsumerTransformer(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = session.CreateTemporaryTopic();
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+
+						consumer.ConsumerTransformer = DoConsumerTransform;
+
+                        IMessage message = session.CreateMessage();
+
+                        message.Properties["Test"] = "Value";
+
+                        producer.Send(message);
+
+                        message = consumer.Receive(TimeSpan.FromMilliseconds(5000));
+
+                        Assert.IsNotNull(message);
+                        Assert.IsTrue(message.Properties.Count == 2, "Property Count should be 2");
+
+                        Assert.AreEqual("Value", message.Properties["Test"], "Property 'Value' was incorrect");
+                        Assert.AreEqual(propertyValue, message.Properties[propertyName], "Property not inserted");
+                    }
+				}
+			}
+		}
+		
+		private IMessage DoProducerTransform(ISession session, IMessageProducer producer, IMessage message)
+		{
+			message.Properties[propertyName] = propertyValue;
+			
+			return message;
+		}
+
+		private IMessage DoConsumerTransform(ISession session, IMessageConsumer consumer, IMessage message)
+		{
+            IMessage newMessage = session.CreateMessage();
+
+            MessageTransformation.CopyNMSMessageProperties(message, newMessage);
+
+			newMessage.Properties[propertyName] = propertyValue;
+
+			return newMessage;
+		}
+	}
+}
+
diff --git a/src/test/csharp/NMSPropertyTest.cs b/src/test/csharp/NMSPropertyTest.cs
new file mode 100644
index 0000000..460faa8
--- /dev/null
+++ b/src/test/csharp/NMSPropertyTest.cs
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class NMSPropertyTest : NMSTest
+	{
+		// standard NMS properties
+		protected string expectedText = "Hey this works!";
+		protected string correlationID = "FooBar";
+		protected MsgPriority priority = MsgPriority.Normal;
+		protected String type = "FooType";
+		protected String groupID = "BarGroup";
+		protected int groupSeq = 1;
+
+		protected NMSPropertyTest(NMSTestSupport testSupport)
+			: base (testSupport)
+		{
+		}
+
+		//[Test]
+		public void TestSendReceiveNMSProperties(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.Priority = priority;
+						producer.DeliveryMode = deliveryMode;
+						ITextMessage request = session.CreateTextMessage(expectedText);
+
+						// Set the headers
+						request.NMSCorrelationID = correlationID;
+						request.NMSType = type;
+						request.Properties["NMSXGroupID"] = groupID;
+						request.Properties["NMSXGroupSeq"] = groupSeq;
+
+						producer.Send(request);
+
+						ITextMessage message = consumer.Receive(receiveTimeout) as ITextMessage;
+
+						Assert.IsNotNull(message, "Did not receive an ITextMessage!");
+						Assert.AreEqual(expectedText, message.Text, "Message text does not match.");
+
+						// compare standard NMS headers
+						Assert.AreEqual(correlationID, message.NMSCorrelationID, "NMSCorrelationID does not match");
+						Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+						Assert.AreEqual(priority, message.NMSPriority, "NMSPriority does not match");
+						Assert.AreEqual(type, message.NMSType, "NMSType does not match");
+						Assert.AreEqual(groupID, message.Properties["NMSXGroupID"], "NMSXGroupID does not match");
+						Assert.AreEqual(groupSeq, message.Properties["NMSXGroupSeq"], "NMSXGroupSeq does not match");
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/test/csharp/NMSTest.cs b/src/test/csharp/NMSTest.cs
new file mode 100644
index 0000000..3fe3fac
--- /dev/null
+++ b/src/test/csharp/NMSTest.cs
@@ -0,0 +1,505 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Xml;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	/// <summary>
+	/// Base class for test cases
+	/// </summary>
+	public abstract class NMSTest
+	{
+		protected TimeSpan receiveTimeout = TimeSpan.FromMilliseconds(15000);
+
+		public static string ToHex(long value)
+		{
+			return String.Format("{0:x}", value);
+		}
+
+		#region Constructors and test support
+
+		private NMSTestSupport testSupport;
+
+		static NMSTest()
+		{
+			Apache.NMS.Tracer.Trace = new NMSTracer();
+		}
+
+		protected NMSTest(NMSTestSupport testSupport)
+		{
+			this.testSupport = testSupport;
+			this.testSupport.TestClassType = this.GetType();
+		}
+
+		#endregion
+
+		#region Set up and tear down
+
+		[SetUp]
+		public virtual void SetUp()
+		{
+			this.testSupport.SetUp();
+		}
+
+		[TearDown]
+		public virtual void TearDown()
+		{
+			this.testSupport.TearDown();
+		}
+
+		#endregion
+
+		#region Configuration file
+
+		/// <summary>
+		/// The configuration document.
+		/// </summary>
+		public XmlDocument ConfigurationDocument
+		{
+			get { return this.testSupport.ConfigurationDocument; }
+		}
+
+		/// <summary>
+		/// Loads the configuration file.
+		/// </summary>
+		/// <returns>XmlDocument of the configuration file</returns>
+		protected virtual XmlDocument LoadConfigFile()
+		{
+			return this.testSupport.LoadConfigFile();
+		}
+
+		/// <summary>
+		/// Loads the configuration file.
+		/// </summary>
+		/// <param name="configFilePath">Configuration file path</param>
+		/// <returns>XmlDocument of the configuration file</returns>
+		protected virtual XmlDocument LoadConfigFile(string configFilePath)
+		{
+			return this.testSupport.LoadConfigFile(configFilePath);
+		}
+
+		/// <summary>
+		/// Gets the path of the configuration filename.
+		/// </summary>
+		/// <returns>Path of the configuration filename</returns>
+		protected virtual string GetConfigFilePath()
+		{
+			return this.testSupport.GetConfigFilePath();
+		}
+
+		/// <summary>
+		/// Gets the environment variable name for the configuration file path.
+		/// </summary>
+		/// <returns>Environment variable name</returns>
+		protected virtual string GetConfigEnvVarName()
+		{
+			return this.testSupport.GetConfigEnvVarName();
+		}
+
+		/// <summary>
+		/// Gets the default name for the configuration filename.
+		/// </summary>
+		/// <returns>Default name of the configuration filename</returns>
+		protected virtual string GetDefaultConfigFileName()
+		{
+			return this.testSupport.GetDefaultConfigFileName();
+		}
+
+		/// <summary>
+		/// Gets the value of the "value" attribute of the specified node.
+		/// </summary>
+		/// <param name="parentNode">Parent node</param>
+		/// <param name="nodeName">Node name</param>
+		/// <param name="defaultVaue">Default value</param>
+		/// <returns></returns>
+		protected virtual string GetNodeValueAttribute(XmlElement parentNode,
+			string nodeName, string defaultVaue)
+		{
+			return this.testSupport.GetNodeValueAttribute(parentNode,
+				nodeName, defaultVaue);
+		}
+
+		#endregion
+
+		#region URI node
+
+		/// <summary>
+		/// Gets the URI node for the default configuration.
+		/// </summary>
+		/// <returns>URI node for the default configuration name</returns>
+		public virtual XmlElement GetURINode()
+		{
+			return this.testSupport.GetURINode();
+		}
+
+		/// <summary>
+		/// Gets the URI node for the default configuration.
+		/// </summary>
+		/// <param name="nameTestURI">Name of the default configuration node
+		/// </param>
+		/// <returns>URI node for the default configuration name</returns>
+		public virtual XmlElement GetURINode(string nameTestURI)
+		{
+			return this.testSupport.GetURINode(nameTestURI);
+		}
+
+		/// <summary>
+		/// Gets the name of the default connection configuration to be loaded.
+		/// </summary>
+		/// <returns>Default configuration name</returns>
+		protected virtual string GetNameTestURI()
+		{
+			return this.testSupport.GetNameTestURI();
+		}
+
+		#endregion
+
+		#region Factory
+
+		private NMSConnectionFactory nmsFactory;
+		/// <summary>
+		/// The connection factory interface property.
+		/// </summary>
+		public IConnectionFactory Factory
+		{
+			get { return this.testSupport.Factory; }
+		}
+
+		/// <summary>
+		/// Create the NMS Factory that can create NMS Connections.
+		/// </summary>
+		/// <returns>Connection factory</returns>
+		protected NMSConnectionFactory CreateNMSFactory()
+		{
+			return this.testSupport.CreateNMSFactory();
+		}
+
+		/// <summary>
+		/// Create the NMS Factory that can create NMS Connections. This
+		/// function loads the connection settings from the configuration file.
+		/// </summary>
+		/// <param name="nameTestURI">The named connection configuration.
+		/// </param>
+		/// <returns>Connection factory</returns>
+		protected NMSConnectionFactory CreateNMSFactory(string nameTestURI)
+		{
+			return this.testSupport.CreateNMSFactory(nameTestURI);
+		}
+
+		/// <summary>
+		/// Get the parameters for the ConnectionFactory from the configuration
+		/// file.
+		/// </summary>
+		/// <param name="uriNode">Parent node of the factoryParams node.</param>
+		/// <returns>Object array of parameter objects to be passsed to provider
+		/// factory object.  Null if no parameters are specified in
+		/// configuration file.</returns>
+		protected object[] GetFactoryParams(XmlElement uriNode)
+		{
+			return this.testSupport.GetFactoryParams(uriNode);
+		}
+
+		#endregion
+
+		#region Client id and connection
+
+		/// <summary>
+		/// Client id.
+		/// </summary>
+		public string ClientId
+		{
+			get { return this.testSupport.ClientId; }
+		}
+
+		/// <summary>
+		/// Gets a new client id.
+		/// </summary>
+		/// <returns>Client id</returns>
+		public virtual string GetTestClientId()
+		{
+			return this.testSupport.GetTestClientId();
+		}
+
+		/// <summary>
+		/// Create a new connection to the broker.
+		/// </summary>
+		/// <returns>New connection</returns>
+		public virtual IConnection CreateConnection()
+		{
+			return this.testSupport.CreateConnection();
+		}
+
+		/// <summary>
+		/// Create a new connection to the broker.
+		/// </summary>
+		/// <param name="newClientId">Client ID of the new connection.</param>
+		/// <returns>New connection</returns>
+		public virtual IConnection CreateConnection(string newClientId)
+		{
+			return this.testSupport.CreateConnection(newClientId);
+		}
+
+		/// <summary>
+		/// Create a new connection to the broker, and start it.
+		/// </summary>
+		/// <returns>Started connection</returns>
+		public virtual IConnection CreateConnectionAndStart()
+		{
+			return this.testSupport.CreateConnectionAndStart();
+		}
+
+		/// <summary>
+		/// Create a new connection to the broker, and start it.
+		/// </summary>
+		/// <param name="newClientId">Client ID of the new connection.</param>
+		/// <returns>Started connection</returns>
+		public virtual IConnection CreateConnectionAndStart(string newClientId)
+		{
+			return this.testSupport.CreateConnectionAndStart(newClientId);
+		}
+
+		#endregion
+
+		#region Destination
+
+		/// <summary>
+		/// Gets a clear destination by its configuration node reference.
+		/// </summary>
+		/// <param name="session">Session</param>
+		/// <param name="destinationNodeReference">Configuration node name for
+        /// the destination URI</param>
+		/// <returns>Destination</returns>
+		public virtual IDestination GetClearDestinationByNodeReference(
+            ISession session, string destinationNodeReference)
+		{
+			return this.testSupport.GetClearDestinationByNodeReference(session, destinationNodeReference);
+		}
+
+		/// <summary>
+		/// Gets a clear destination. This will try to delete an existing
+		/// destination and re-create it.
+		/// </summary>
+		/// <param name="session">Session</param>
+		/// <param name="destinationURI">Destination URI</param>
+		/// <returns>Clear destination</returns>
+		public virtual IDestination GetClearDestination(ISession session,
+			string destinationURI)
+		{
+			return this.testSupport.GetClearDestination(session, destinationURI);
+		}
+
+		/// <summary>
+		/// Gets an existing destination. Don't clear its contents.
+		/// </summary>
+		/// <param name="session">Session</param>
+		/// <param name="destinationNodeReference">Configuration node name for
+        /// the destination URI</param>
+		/// <returns>Destination</returns>
+		public virtual IDestination GetDestinationByNodeReference(ISession session,
+			string destinationNodeReference)
+		{
+			return this.testSupport.GetDestinationByNodeReference(session, destinationNodeReference);
+		}
+
+		/// <summary>
+		/// Gets a destination URI.
+		/// </summary>
+		/// <param name="destinationNodeReference">Configuration node name for the
+		/// destination URI</param>
+		/// <returns>Destination URI</returns>
+		public virtual string GetDestinationURI(string destinationNodeReference)
+		{
+			return this.testSupport.GetDestinationURI(destinationNodeReference);
+		}
+
+		#endregion
+
+		#region Durable consumer
+
+		/// <summary>
+		/// Register a durable consumer
+		/// </summary>
+		/// <param name="connectionID">Connection ID of the consumer.</param>
+		/// <param name="destination">Destination name to register.  Supports
+		/// embedded prefix names.</param>
+		/// <param name="consumerID">Name of the durable consumer.</param>
+		/// <param name="selector">Selector parameters for consumer.</param>
+		/// <param name="noLocal"></param>
+		protected void RegisterDurableConsumer(string connectionID,
+			string destination, string consumerID, string selector, bool noLocal)
+		{
+			using(IConnection connection = CreateConnection(connectionID))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(
+					AcknowledgementMode.DupsOkAcknowledge))
+				{
+					ITopic destinationTopic = (ITopic)SessionUtil.GetDestination(session, destination);
+					Assert.IsNotNull(destinationTopic, "Could not get destination topic.");
+
+					using(IMessageConsumer consumer = session.CreateDurableConsumer(destinationTopic, consumerID, selector, noLocal))
+					{
+						Assert.IsNotNull(consumer, "Could not create durable consumer.");
+					}
+				}
+			}
+		}
+
+		/// <summary>
+		/// Unregister a durable consumer for the given connection ID.
+		/// </summary>
+		/// <param name="connectionID">Connection ID of the consumer.</param>
+		/// <param name="consumerID">Name of the durable consumer.</param>
+		protected void UnregisterDurableConsumer(string connectionID, string consumerID)
+		{
+			using(IConnection connection = CreateConnection(connectionID))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.DupsOkAcknowledge))
+				{
+					session.DeleteDurableConsumer(consumerID);
+				}
+			}
+		}
+
+		#endregion
+
+		#region Send messages
+
+		/// <summary>
+		/// Sends a specified number of text messages to the designated
+		/// destination.
+		/// </summary>
+		/// <param name="destination">Destination.</param>
+		/// <param name="deliveryMode">Delivery mode.</param>
+		/// <param name="count">Number of messages to be sent.</param>
+		public void SendMessages(IDestination destination,
+			MsgDeliveryMode deliveryMode, int count)
+		{
+			IConnection connection = CreateConnection();
+			connection.Start();
+			SendMessages(connection, destination, deliveryMode, count);
+			connection.Close();
+		}
+
+		/// <summary>
+		/// Sends a specified number of text messages to the designated
+		/// destination.
+		/// </summary>
+		/// <param name="connection">Connection.</param>
+		/// <param name="destination">Destination.</param>
+		/// <param name="deliveryMode">Delivery mode.</param>
+		/// <param name="count">Number of messages to be sent.</param>
+		public void SendMessages(IConnection connection,
+			IDestination destination, MsgDeliveryMode deliveryMode, int count)
+		{
+			ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+			SendMessages(session, destination, deliveryMode, count);
+			session.Close();
+		}
+
+		/// <summary>
+		/// Sends a specified number of text messages to the designated
+		/// destination.
+		/// </summary>
+		/// <param name="session">Session.</param>
+		/// <param name="destination">Destination.</param>
+		/// <param name="deliveryMode">Delivery mode.</param>
+		/// <param name="count">Number of messages to be sent.</param>
+		public void SendMessages(ISession session, IDestination destination,
+			MsgDeliveryMode deliveryMode, int count)
+		{
+			IMessageProducer producer = session.CreateProducer(destination);
+			producer.DeliveryMode = deliveryMode;
+			for(int i = 0; i < count; i++)
+			{
+				producer.Send(session.CreateTextMessage("" + i));
+			}
+			producer.Close();
+		}
+
+		#endregion
+
+		#region Check messages
+
+		protected void AssertTextMessagesEqual(IMessage[] firstSet, IMessage[] secondSet)
+		{
+			AssertTextMessagesEqual(firstSet, secondSet, "");
+		}
+
+		protected void AssertTextMessagesEqual(IMessage[] firstSet, IMessage[] secondSet, string messsage)
+		{
+			Assert.AreEqual(firstSet.Length, secondSet.Length, "Message count does not match: " + messsage);
+
+			for(int i = 0; i < secondSet.Length; i++)
+			{
+				ITextMessage m1 = firstSet[i] as ITextMessage;
+				ITextMessage m2 = secondSet[i] as ITextMessage;
+
+				AssertTextMessageEqual(m1, m2, "Message " + (i + 1) + " did not match : ");
+			}
+		}
+
+		protected void AssertEquals(ITextMessage m1, ITextMessage m2)
+		{
+			AssertEquals(m1, m2, "");
+		}
+
+		protected void AssertTextMessageEqual(ITextMessage m1, ITextMessage m2, string message)
+		{
+			Assert.IsFalse(m1 == null ^ m2 == null, message + ": expected {" + m1 + "}, but was {" + m2 + "}");
+
+			if(m1 == null)
+			{
+				return;
+			}
+
+			Assert.AreEqual(m1.Text, m2.Text, message);
+		}
+
+		protected void AssertEquals(IMessage m1, IMessage m2)
+		{
+			AssertEquals(m1, m2, "");
+		}
+
+		protected void AssertEquals(IMessage m1, IMessage m2, string message)
+		{
+			Assert.IsFalse(m1 == null ^ m2 == null, message + ": expected {" + m1 + "}, but was {" + m2 + "}");
+
+			if(m1 == null)
+			{
+				return;
+			}
+
+			Assert.IsTrue(m1.GetType() == m2.GetType(), message + ": expected {" + m1 + "}, but was {" + m2 + "}");
+
+			if(m1 is ITextMessage)
+			{
+				AssertTextMessageEqual((ITextMessage) m1, (ITextMessage) m2, message);
+			}
+			else
+			{
+				Assert.AreEqual(m1, m2, message);
+			}
+		}
+
+		#endregion
+	}
+}
diff --git a/src/test/csharp/NMSTestSupport.cs b/src/test/csharp/NMSTestSupport.cs
new file mode 100644
index 0000000..31f2e11
--- /dev/null
+++ b/src/test/csharp/NMSTestSupport.cs
@@ -0,0 +1,637 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Xml;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+using Apache.NMS.MSMQ;
+
+namespace Apache.NMS.Test
+{
+	/// <summary>
+	/// Useful class for test cases support.
+	/// </summary>
+	public class NMSTestSupport
+	{
+		protected TimeSpan receiveTimeout = TimeSpan.FromMilliseconds(15000);
+		protected int testRun;
+		protected int idCounter;
+
+        protected Type testClassType;
+		public Type TestClassType
+		{
+			get { return this.testClassType; }
+			set { this.testClassType = value; }
+		}
+
+		#region Constructors
+
+		public NMSTestSupport()
+		{
+		}
+
+		#endregion
+
+		#region Set up and tear down
+
+		public virtual void SetUp()
+		{
+			this.testRun++;
+		}
+
+		public virtual void TearDown()
+		{
+		}
+
+		#endregion
+
+		#region Configuration file
+
+		private XmlDocument configurationDocument = null;
+		/// <summary>
+		/// The configuration document.
+		/// </summary>
+		public XmlDocument ConfigurationDocument
+		{
+			get
+			{
+				if(this.configurationDocument == null)
+				{
+					this.configurationDocument = LoadConfigFile();
+					Assert.IsTrue(this.configurationDocument != null,
+						"Error loading configuration.");
+				}
+
+				return this.configurationDocument;
+			}
+		}
+
+		/// <summary>
+		/// Loads the configuration file.
+		/// </summary>
+		/// <returns>XmlDocument of the configuration file</returns>
+		public virtual XmlDocument LoadConfigFile()
+		{
+			return LoadConfigFile(GetConfigFilePath());
+		}
+
+		/// <summary>
+		/// Loads the configuration file.
+		/// </summary>
+		/// <param name="configFilePath">Configuration file path</param>
+		/// <returns>XmlDocument of the configuration file</returns>
+		public virtual XmlDocument LoadConfigFile(string configFilePath)
+		{
+			XmlDocument configDoc = new XmlDocument();
+
+			configDoc.Load(configFilePath);
+
+			return configDoc;
+		}
+
+		/// <summary>
+		/// Gets the path of the configuration filename.
+		/// </summary>
+		/// <returns>Path of the configuration filename</returns>
+		public virtual string GetConfigFilePath()
+		{
+			// The full path may be specified by an environment variable
+			string configFilePath = GetEnvVar(GetConfigEnvVarName(), "");
+			bool configFound = (!string.IsNullOrEmpty(configFilePath)
+				&& File.Exists(configFilePath));
+
+			// Else it may be found in well known locations
+			if(!configFound)
+			{
+				string[] paths = GetConfigSearchPaths();
+				string configFileName = GetDefaultConfigFileName();
+
+				foreach(string path in paths)
+				{
+					string fullpath = Path.Combine(path, configFileName);
+					Tracer.Debug("\tScanning folder: " + path);
+
+					if(File.Exists(fullpath))
+					{
+						Tracer.Debug("\tAssembly found!");
+						configFilePath = fullpath;
+						configFound = true;
+						break;
+					}
+				}
+			}
+
+			Tracer.Debug("\tConfig file: " + configFilePath);
+			Assert.IsTrue(configFound, "Connection configuration file does not exist.");
+			return configFilePath;
+		}
+
+		/// <summary>
+		/// Gets the environment variable name for the configuration file path.
+		/// </summary>
+		/// <returns>Environment variable name</returns>
+		public virtual string GetConfigEnvVarName()
+		{
+			return "NMSTESTCONFIGPATH";
+		}
+
+		/// <summary>
+		/// Gets the default name for the configuration filename.
+		/// </summary>
+		/// <returns>Default name of the configuration filename</returns>
+		public virtual string GetDefaultConfigFileName()
+		{
+			return "nmsprovider-test.config";
+		}
+
+		/// <summary>
+		/// Gets an array of paths where the configuration file sould be found.
+		/// </summary>
+		/// <returns>Array of paths</returns>
+		private static string[] GetConfigSearchPaths()
+		{
+			ArrayList pathList = new ArrayList();
+
+			// Check the current folder first.
+			pathList.Add("");
+#if !NETCF
+			AppDomain currentDomain = AppDomain.CurrentDomain;
+
+			// Check the folder the assembly is located in.
+			pathList.Add(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
+			if(null != currentDomain.BaseDirectory)
+			{
+				pathList.Add(currentDomain.BaseDirectory);
+			}
+
+			if(null != currentDomain.RelativeSearchPath)
+			{
+				pathList.Add(currentDomain.RelativeSearchPath);
+			}
+#endif
+
+			return (string[]) pathList.ToArray(typeof(string));
+		}
+
+		/// <summary>
+		/// Gets the value of the "value" attribute of the specified node.
+		/// </summary>
+		/// <param name="parentNode">Parent node</param>
+		/// <param name="nodeName">Node name</param>
+		/// <param name="defaultVaue">Default value</param>
+		/// <returns></returns>
+		public string GetNodeValueAttribute(XmlElement parentNode,
+			string nodeName, string defaultVaue)
+		{
+			XmlElement node = (XmlElement)parentNode.SelectSingleNode(nodeName);
+
+			return (node == null ? defaultVaue : node.GetAttribute("value"));
+		}
+
+		#endregion
+
+		#region URI node
+
+		/// <summary>
+		/// Gets the URI node for the default configuration.
+		/// </summary>
+		/// <returns>URI node for the default configuration name</returns>
+		public virtual XmlElement GetURINode()
+		{
+			return GetURINode(GetNameTestURI());
+		}
+
+		/// <summary>
+		/// Gets the URI node for the default configuration.
+		/// </summary>
+		/// <param name="nameTestURI">Name of the default configuration node
+		/// </param>
+		/// <returns>URI node for the default configuration name</returns>
+		public virtual XmlElement GetURINode(string nameTestURI)
+		{
+			return (XmlElement)ConfigurationDocument.SelectSingleNode(
+				String.Format("/configuration/{0}", nameTestURI));
+		}
+
+		/// <summary>
+		/// Gets the name of the default connection configuration to be loaded.
+		/// </summary>
+		/// <returns>Default configuration name</returns>
+		public virtual string GetNameTestURI()
+		{
+			return "testURI";
+		}
+
+		#endregion
+
+		#region Factory
+
+		private NMSConnectionFactory nmsFactory;
+		/// <summary>
+		/// The connection factory interface property.
+		/// </summary>
+		public IConnectionFactory Factory
+		{
+			get
+			{
+				if(this.nmsFactory == null)
+				{
+					this.nmsFactory = CreateNMSFactory();
+
+					Assert.IsNotNull(this.nmsFactory, "Error creating factory.");
+				}
+
+				return this.nmsFactory.ConnectionFactory;
+			}
+		}
+
+		/// <summary>
+		/// Create the NMS Factory that can create NMS Connections.
+		/// </summary>
+		/// <returns>Connection factory</returns>
+		public NMSConnectionFactory CreateNMSFactory()
+		{
+			return CreateNMSFactory(GetNameTestURI());
+		}
+
+		/// <summary>
+		/// Create the NMS Factory that can create NMS Connections. This
+		/// function loads the connection settings from the configuration file.
+		/// </summary>
+		/// <param name="nameTestURI">The named connection configuration.
+		/// </param>
+		/// <returns>Connection factory</returns>
+		public NMSConnectionFactory CreateNMSFactory(string nameTestURI)
+		{
+			XmlElement uriNode = GetURINode(nameTestURI);
+
+			Uri brokerUri = null;
+			object[] factoryParams = null;
+			if(uriNode != null)
+			{
+				// Replace any environment variables embedded inside the string.
+				brokerUri = new Uri(uriNode.GetAttribute("value"));
+				factoryParams = GetFactoryParams(uriNode);
+				cnxClientId = GetNodeValueAttribute(uriNode, "cnxClientId", "NMSTestClientId");
+				cnxUserName = GetNodeValueAttribute(uriNode, "cnxUserName", null);
+				cnxPassWord = GetNodeValueAttribute(uriNode, "cnxPassWord", null);
+			}
+
+			if(factoryParams == null)
+			{
+				this.nmsFactory = new Apache.NMS.NMSConnectionFactory(brokerUri);
+			}
+			else
+			{
+				this.nmsFactory = new Apache.NMS.NMSConnectionFactory(brokerUri, factoryParams);
+			}
+
+			return this.nmsFactory;
+		}
+
+		/// <summary>
+		/// Get the parameters for the ConnectionFactory from the configuration
+		/// file.
+		/// </summary>
+		/// <param name="uriNode">Parent node of the factoryParams node.</param>
+		/// <returns>Object array of parameter objects to be passsed to provider
+		/// factory object.  Null if no parameters are specified in
+		/// configuration file.</returns>
+		public object[] GetFactoryParams(XmlElement uriNode)
+		{
+			ArrayList factoryParams = new ArrayList();
+			XmlElement factoryParamsNode = (XmlElement)uriNode.SelectSingleNode("factoryParams");
+
+			if(factoryParamsNode != null)
+			{
+				XmlNodeList nodeList = factoryParamsNode.SelectNodes("param");
+
+				if(nodeList != null)
+				{
+					foreach(XmlElement paramNode in nodeList)
+					{
+						string paramType = paramNode.GetAttribute("type");
+						string paramValue = paramNode.GetAttribute("value");
+
+						switch(paramType)
+						{
+							case "string":
+								factoryParams.Add(paramValue);
+								break;
+
+							case "int":
+								factoryParams.Add(int.Parse(paramValue));
+								break;
+
+							// TODO: Add more parameter types
+						}
+					}
+				}
+			}
+
+			if(factoryParams.Count > 0)
+			{
+				return factoryParams.ToArray();
+			}
+
+			return null;
+		}
+
+		#endregion
+
+		#region Environment variables
+
+		/// <summary>
+		/// Get environment variable value.
+		/// </summary>
+		/// <param name="varName"></param>
+		/// <param name="defaultValue"></param>
+		/// <returns></returns>
+		public static string GetEnvVar(string varName, string defaultValue)
+		{
+#if (PocketPC||NETCF||NETCF_2_0)
+            string varValue = null;
+#else
+			string varValue = Environment.GetEnvironmentVariable(varName);
+#endif
+			if(null == varValue)
+			{
+				varValue = defaultValue;
+			}
+
+			return varValue;
+		}
+
+		#endregion
+
+		#region Client id and connection
+
+		protected string cnxClientId;
+		/// <summary>
+		/// Client id.
+		/// </summary>
+		public string ClientId
+		{
+			get { return this.cnxClientId; }
+		}
+
+		/// <summary>
+		/// Gets a new client id.
+		/// </summary>
+		/// <returns>Client id</returns>
+		public virtual string GetTestClientId()
+		{
+			System.Text.StringBuilder id = new System.Text.StringBuilder();
+
+			id.Append("ID:");
+			id.Append(this.GetType().Name);
+			id.Append(":");
+			id.Append(this.testRun);
+			id.Append(":");
+			id.Append(++idCounter);
+
+			return id.ToString();
+		}
+
+		protected string cnxUserName;
+		/// <summary>
+		/// User name.
+		/// </summary>
+		public string UserName
+		{
+			get { return this.cnxUserName; }
+		}
+
+		protected string cnxPassWord;
+		/// <summary>
+		/// User pass word.
+		/// </summary>
+		public string PassWord
+		{
+			get { return this.cnxPassWord; }
+		}
+
+		/// <summary>
+		/// Create a new connection to the broker.
+		/// </summary>
+		/// <returns>New connection</returns>
+		public virtual IConnection CreateConnection()
+		{
+			return CreateConnection(null);
+		}
+
+		/// <summary>
+		/// Create a new connection to the broker.
+		/// </summary>
+		/// <param name="newClientId">Client ID of the new connection.</param>
+		/// <returns>New connection</returns>
+		public virtual IConnection CreateConnection(string newClientId)
+		{
+			IConnection newConnection;
+
+			if(this.cnxUserName == null)
+			{
+				newConnection = Factory.CreateConnection();
+			}
+			else
+			{
+				newConnection = Factory.CreateConnection(cnxUserName, cnxPassWord);
+			}
+
+			Assert.IsNotNull(newConnection, "Connection not created");
+
+			if(newClientId != null)
+			{
+				newConnection.ClientId = newClientId;
+			}
+
+			return newConnection;
+		}
+
+		/// <summary>
+		/// Create a new connection to the broker, and start it.
+		/// </summary>
+		/// <returns>Started connection</returns>
+		public virtual IConnection CreateConnectionAndStart()
+		{
+			return CreateConnectionAndStart(null);
+		}
+
+		/// <summary>
+		/// Create a new connection to the broker, and start it.
+		/// </summary>
+		/// <param name="newClientId">Client ID of the new connection.</param>
+		/// <returns>Started connection</returns>
+		public virtual IConnection CreateConnectionAndStart(string newClientId)
+		{
+			IConnection newConnection = CreateConnection(newClientId);
+			newConnection.Start();
+			return newConnection;
+		}
+
+		#endregion
+
+		#region Destination
+
+		/// <summary>
+		/// Gets a clear destination by its configuration node reference.
+		/// </summary>
+		/// <param name="session">Session</param>
+		/// <param name="destinationNodeReference">Configuration node name for
+        /// the destination URI</param>
+		/// <returns>Destination</returns>
+		public virtual IDestination GetClearDestinationByNodeReference(
+            ISession session, string destinationNodeReference)
+		{
+			string uri = GetDestinationURI(destinationNodeReference);
+			return GetClearDestination(session, uri);
+		}
+
+		/// <summary>
+		/// Gets a clear destination. This will try to delete an existing
+		/// destination and re-create it.
+		/// </summary>
+		/// <param name="session">Session</param>
+		/// <param name="destinationURI">Destination URI</param>
+		/// <returns>Clear destination</returns>
+		public virtual IDestination GetClearDestination(ISession session,
+			string destinationURI)
+		{
+			IDestination destination;
+
+			try
+			{
+				DeleteDestination(session, destinationURI);
+				destination = CreateDestination(session, destinationURI);
+			}
+			catch(Exception)
+			{
+				// Can't delete it, so lets try and purge it.
+				destination = SessionUtil.GetDestination(session, destinationURI);
+
+				using(IMessageConsumer consumer = session.CreateConsumer(destination))
+				{
+					while(consumer.Receive(TimeSpan.FromMilliseconds(750)) != null)
+					{
+					}
+				}
+			}
+
+			return destination;
+		}
+
+		/// <summary>
+		/// Deletes a destination.
+		/// </summary>
+		/// <param name="session">Session</param>
+		/// <param name="destinationURI">Destination URI</param>
+		protected virtual void DeleteDestination(ISession session,
+			string destinationURI)
+		{
+			// Only delete the destination if it can be recreated
+			// SessionUtil.DeleteDestination(session, destinationURI, DestinationType.Queue)
+			throw new NotSupportedException();
+		}
+
+		/// <summary>
+		/// Creates a destination.
+		/// </summary>
+		/// <param name="session">Session</param>
+		/// <param name="destinationURI">Destination URI</param>
+		protected virtual IDestination CreateDestination(ISession session,
+			string destinationURI)
+		{
+			throw new NotSupportedException();
+		}
+
+		/// <summary>
+		/// Gets an existing destination. Don't clear its contents.
+		/// </summary>
+		/// <param name="session">Session</param>
+		/// <param name="destinationNodeReference">Configuration node name for
+		/// the destination URI</param>
+		/// <returns>Destination</returns>
+		public virtual IDestination GetDestinationByNodeReference(
+            ISession session, string destinationNodeReference)
+		{
+			string uri = GetDestinationURI(destinationNodeReference);
+
+			IDestination destination = SessionUtil.GetDestination(session, uri);
+
+			return destination;
+		}
+
+		/// <summary>
+		/// Gets a destination URI.
+		/// </summary>
+		/// <param name="destinationNodeReference">Configuration node name for
+        /// the destination URI</param>
+		/// <returns>Destination URI</returns>
+		public virtual string GetDestinationURI(
+			string destinationNodeReference)
+		{
+			string uri = null;
+
+			if(!string.IsNullOrEmpty(destinationNodeReference))
+			{
+				XmlElement uriNode = GetURINode();
+
+				if(uriNode != null)
+				{
+					uri = GetNodeValueAttribute(uriNode, destinationNodeReference, null);
+				}
+			}
+
+			if(string.IsNullOrEmpty(uri))
+			{
+				uri = NewDestinationURI(destinationNodeReference);
+			}
+
+			return uri;
+		}
+
+		/// <summary>
+		/// Gets a new destination URI for the specified URI scheme (valid
+        /// values are "queue://", "topic://", "temp-queue://" and
+        /// "temp-topic://").
+		/// </summary>
+		/// <param name="destinationTypeScheme">Destination type</param>
+		/// <returns>Destination URI</returns>
+		public virtual string NewDestinationURI(string destinationTypeScheme)
+		{
+            if(destinationTypeScheme != "queue://" &&
+               destinationTypeScheme != "topic://" &&
+               destinationTypeScheme != "temp-queue://" &&
+               destinationTypeScheme != "temp-topic://")
+            {
+                throw new ArgumentException(
+                    string.Format("Invalid destination type scheme \"{0}\".",
+                    destinationTypeScheme));
+            }
+
+			return destinationTypeScheme + "TEST." + this.TestClassType.Name
+						+ "." + Guid.NewGuid().ToString();
+		}
+
+		#endregion
+	}
+}
diff --git a/src/test/csharp/NMSTracer.cs b/src/test/csharp/NMSTracer.cs
new file mode 100644
index 0000000..448e232
--- /dev/null
+++ b/src/test/csharp/NMSTracer.cs
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define TRACE	// Force tracing to be enabled for this class
+
+namespace Apache.NMS.Test
+{
+	public class NMSTracer : Apache.NMS.ITrace
+	{
+		#region ITrace Members
+		public void Debug(string message)
+		{
+#if !NETCF
+			System.Diagnostics.Trace.WriteLine(string.Format("DEBUG: {0}", message));
+#endif
+		}
+
+		public void Error(string message)
+		{
+#if !NETCF
+			System.Diagnostics.Trace.WriteLine(string.Format("ERROR: {0}", message));
+#endif
+		}
+
+		public void Fatal(string message)
+		{
+#if !NETCF
+			System.Diagnostics.Trace.WriteLine(string.Format("FATAL: {0}", message));
+#endif
+		}
+
+		public void Info(string message)
+		{
+#if !NETCF
+			System.Diagnostics.Trace.WriteLine(string.Format("INFO: {0}", message));
+#endif
+		}
+
+		public void Warn(string message)
+		{
+#if !NETCF
+			System.Diagnostics.Trace.WriteLine(string.Format("WARN: {0}", message));
+#endif
+		}
+
+		public bool IsDebugEnabled
+		{
+			get { return true; }
+		}
+
+		public bool IsErrorEnabled
+		{
+			get { return true; }
+		}
+
+		public bool IsFatalEnabled
+		{
+			get { return true; }
+		}
+
+		public bool IsInfoEnabled
+		{
+			get { return true; }
+		}
+
+		public bool IsWarnEnabled
+		{
+			get { return true; }
+		}
+
+		#endregion
+	}
+}
diff --git a/src/test/csharp/PrimitiveMapTest.cs b/src/test/csharp/PrimitiveMapTest.cs
new file mode 100644
index 0000000..3e20892
--- /dev/null
+++ b/src/test/csharp/PrimitiveMapTest.cs
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	[TestFixture]
+	public class PrimitiveMapTest
+	{
+
+		bool a = true;
+		byte b = 123;
+		char c = 'c';
+		short d = 0x1234;
+		int e = 0x12345678;
+		long f = 0x1234567812345678;
+		string g = "Hello World!";
+		bool h = false;
+		byte i = 0xFF;
+		short j = -0x1234;
+		int k = -0x12345678;
+		long l = -0x1234567812345678;
+		IList m = CreateList();
+		IDictionary n = CreateDictionary();
+
+		[Test]
+		public void TestNotMarshalled()
+		{
+			PrimitiveMap map = CreatePrimitiveMap();
+			AssertPrimitiveMap(map);
+		}
+
+		[Test]
+		public void TestMarshalled()
+		{
+			PrimitiveMap map = CreatePrimitiveMap();
+			byte[] data = map.Marshal();
+			map = PrimitiveMap.Unmarshal(data);
+			AssertPrimitiveMap(map);
+		}
+
+		[Test]
+		public void TestMarshalledWithBigString()
+		{
+			PrimitiveMap map = CreatePrimitiveMap();
+			String test = new String('a', 65538);
+			map.SetString("BIG_STRING", test);
+			byte[] data = map.Marshal();
+			map = PrimitiveMap.Unmarshal(data);
+			AssertPrimitiveMap(map);
+			Assert.AreEqual(test, map.GetString("BIG_STRING"));
+		}
+
+		protected PrimitiveMap CreatePrimitiveMap()
+		{
+			PrimitiveMap map = new PrimitiveMap();
+
+			map["a"] = a;
+			map["b"] = b;
+			map["c"] = c;
+			map["d"] = d;
+			map["e"] = e;
+			map["f"] = f;
+			map["g"] = g;
+			map["h"] = h;
+			map["i"] = i;
+			map["j"] = j;
+			map["k"] = k;
+			map["l"] = l;
+			map["m"] = m;
+			map["n"] = n;
+
+			return map;
+		}
+
+		protected void AssertPrimitiveMap(PrimitiveMap map)
+		{
+			// use generic API to access entries
+			Assert.AreEqual(a, map["a"], "generic map entry: a");
+			Assert.AreEqual(b, map["b"], "generic map entry: b");
+			Assert.AreEqual(c, map["c"], "generic map entry: c");
+			Assert.AreEqual(d, map["d"], "generic map entry: d");
+			Assert.AreEqual(e, map["e"], "generic map entry: e");
+			Assert.AreEqual(f, map["f"], "generic map entry: f");
+			Assert.AreEqual(g, map["g"], "generic map entry: g");
+			Assert.AreEqual(h, map["h"], "generic map entry: h");
+			Assert.AreEqual(i, map["i"], "generic map entry: i");
+			Assert.AreEqual(j, map["j"], "generic map entry: j");
+			Assert.AreEqual(k, map["k"], "generic map entry: k");
+			Assert.AreEqual(l, map["l"], "generic map entry: l");
+			//Assert.AreEqual(m, map["m"], "generic map entry: m");
+			//Assert.AreEqual(n, map["n"], "generic map entry: n");
+
+			// use type safe APIs
+			Assert.AreEqual(a, map.GetBool("a"), "map entry: a");
+			Assert.AreEqual(b, map.GetByte("b"), "map entry: b");
+			Assert.AreEqual(c, map.GetChar("c"), "map entry: c");
+			Assert.AreEqual(d, map.GetShort("d"), "map entry: d");
+			Assert.AreEqual(e, map.GetInt("e"), "map entry: e");
+			Assert.AreEqual(f, map.GetLong("f"), "map entry: f");
+			Assert.AreEqual(g, map.GetString("g"), "map entry: g");
+			Assert.AreEqual(h, map.GetBool("h"), "map entry: h");
+			Assert.AreEqual(i, map.GetByte("i"), "map entry: i");
+			Assert.AreEqual(j, map.GetShort("j"), "map entry: j");
+			Assert.AreEqual(k, map.GetInt("k"), "map entry: k");
+			Assert.AreEqual(l, map.GetLong("l"), "map entry: l");
+			//Assert.AreEqual(m, map.GetList("m"), "map entry: m");
+			//Assert.AreEqual(n, map.GetDictionary("n"), "map entry: n");
+
+			IList list = map.GetList("m");
+			Assert.AreEqual(2, list.Count, "list size");
+			Assert.IsTrue(list.Contains("Item1"));
+			Assert.IsTrue(list.Contains("Item2"));
+
+			IDictionary dictionary = map.GetDictionary("n");
+			Assert.AreEqual(5, dictionary.Count, "dictionary size");
+
+			IDictionary childMap = (IDictionary) dictionary["childMap"];
+			Assert.IsNotNull(childMap);
+			Assert.AreEqual("childMap", childMap["name"], "childMap[name]");
+
+			IList childList = (IList) dictionary["childList"];
+			Assert.IsNotNull(childList);
+			Assert.IsTrue(childList.Contains("childListElement1"));
+		}
+
+		protected static IList CreateList()
+		{
+			ArrayList answer = new ArrayList();
+			answer.Add("Item1");
+			answer.Add("Item2");
+			return answer;
+		}
+
+		protected static IDictionary CreateDictionary()
+		{
+			Hashtable answer = new Hashtable();
+			answer.Add("Name", "James");
+			answer.Add("Location", "London");
+			answer.Add("Company", "LogicBlaze");
+
+			Hashtable childMap = new Hashtable();
+			childMap.Add("name", "childMap");
+			answer.Add("childMap", childMap);
+
+			ArrayList childList = new ArrayList();
+			childList.Add("childListElement1");
+			answer.Add("childList", childList);
+			return answer;
+		}
+	}
+}
diff --git a/src/test/csharp/ProducerTest.cs b/src/test/csharp/ProducerTest.cs
new file mode 100644
index 0000000..ffe058e
--- /dev/null
+++ b/src/test/csharp/ProducerTest.cs
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class ProducerTest : NMSTest
+	{
+		protected ProducerTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+        //[Test]
+        public virtual void TestProducerSendToNullDestinationWithoutDefault()
+        {
+            using(IConnection connection = CreateConnection(GetTestClientId()))
+            {
+                connection.Start();
+                using(ISession session = connection.CreateSession())
+                {
+                    IMessageProducer producer = session.CreateProducer(null);
+
+                    try
+                    {
+                        producer.Send(null, session.CreateTextMessage("Message"));
+                        Assert.Fail("Producer should have thrown an NotSupportedException");
+                    }
+                    catch(NotSupportedException)
+                    {
+                    }
+                    catch(Exception ex)
+                    {
+                        Assert.Fail("Wrong Exception Type Thrown: " + ex.GetType().Name);
+                    }
+                }
+            }
+        }
+
+        //[Test]
+        public virtual void TestProducerSendToNullDestinationWithDefault(string testDestRef)
+        {
+            using(IConnection connection = CreateConnection(GetTestClientId()))
+            {
+                connection.Start();
+                using(ISession session = connection.CreateSession())
+                {
+                    IDestination unusedDest = GetClearDestinationByNodeReference(session, testDestRef);
+
+                    IMessageProducer producer = session.CreateProducer(unusedDest);
+
+                    try
+                    {
+                        producer.Send(null, session.CreateTextMessage("Message"));
+                        Assert.Fail("Producer should have thrown an InvalidDestinationException");
+                    }
+                    catch(InvalidDestinationException)
+                    {
+                    }
+                    catch(Exception ex)
+                    {
+                        Assert.Fail("Wrong Exception Type Thrown: " + ex.GetType().Name);
+                    }
+                }
+            }
+        }
+
+		//[Test]
+		public virtual void TestProducerSendToNonDefaultDestination(string unusedTestDestRef, string usedTestDestRef)
+		{
+            using(IConnection connection = CreateConnection(GetTestClientId()))
+            {
+                connection.Start();
+                using(ISession session = connection.CreateSession())
+                {
+					IDestination unusedDest = GetClearDestinationByNodeReference(session, unusedTestDestRef);
+					IDestination usedDest = GetClearDestinationByNodeReference(session, usedTestDestRef);
+
+					IMessageProducer producer = session.CreateProducer(unusedDest);
+
+                    try
+                    {
+					    producer.Send(usedDest, session.CreateTextMessage("Message"));
+                        Assert.Fail("Producer should have thrown an NotSupportedException");
+                    }
+                    catch(NotSupportedException)
+                    {
+                    }
+                    catch(Exception ex)
+                    {
+                        Assert.Fail("Wrong Exception Type Thrown: " + ex.GetType().Name);
+                    }
+				}
+			}
+        }
+	}
+}
diff --git a/src/test/csharp/RedeliveryPolicyTest.cs b/src/test/csharp/RedeliveryPolicyTest.cs
new file mode 100644
index 0000000..0ee9f54
--- /dev/null
+++ b/src/test/csharp/RedeliveryPolicyTest.cs
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using Apache.NMS.Policies;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+    [TestFixture]
+    public class RedeliveryPolicyTest
+    {
+        [Test]
+        public void Executes_redelivery_policy_with_backoff_enabled_correctly()
+        {
+            RedeliveryPolicy policy = new RedeliveryPolicy();
+
+            policy.BackOffMultiplier = 2;
+            policy.InitialRedeliveryDelay = 5;
+            policy.UseExponentialBackOff = true;
+
+            // simulate a retry of 10 times
+            Assert.IsTrue(policy.RedeliveryDelay(0) == 0, "redelivery delay not 5 is " + policy.RedeliveryDelay(0));
+            Assert.IsTrue(policy.RedeliveryDelay(1) == 5, "redelivery delay not 10 is " + policy.RedeliveryDelay(1));
+            Assert.IsTrue(policy.RedeliveryDelay(2) == 10, "redelivery delay not 20 is " + policy.RedeliveryDelay(2));
+            Assert.IsTrue(policy.RedeliveryDelay(3) == 20, "redelivery delay not 40 is " + policy.RedeliveryDelay(3));
+            Assert.IsTrue(policy.RedeliveryDelay(4) == 40, "redelivery delay not 80 is " + policy.RedeliveryDelay(4));
+            Assert.IsTrue(policy.RedeliveryDelay(5) == 80, "redelivery delay not 160 is " + policy.RedeliveryDelay(5));
+            Assert.IsTrue(policy.RedeliveryDelay(6) == 160, "redelivery delay not 320 is " + policy.RedeliveryDelay(6));
+            Assert.IsTrue(policy.RedeliveryDelay(7) == 320, "redelivery delay not 640 is " + policy.RedeliveryDelay(7));
+            Assert.IsTrue(policy.RedeliveryDelay(8) == 640, "redelivery delay not 1280 is " + policy.RedeliveryDelay(8));
+            Assert.IsTrue(policy.RedeliveryDelay(9) == 1280, "redelivery delay not 2560 is " + policy.RedeliveryDelay(9));
+        }
+
+        [Test]
+        public void Executes_redelivery_policy_with_backoff_of_3_enabled_correctly()
+        {
+            RedeliveryPolicy policy = new RedeliveryPolicy();
+
+            policy.BackOffMultiplier = 3;
+            policy.InitialRedeliveryDelay = 3;
+            policy.UseExponentialBackOff = true;
+
+            // simulate a retry of 10 times
+            Assert.IsTrue(policy.RedeliveryDelay(0) == 0, "redelivery delay not 5 is " + policy.RedeliveryDelay(0));
+            Assert.IsTrue(policy.RedeliveryDelay(1) == 3, "redelivery delay not 10 is " + policy.RedeliveryDelay(1));
+            Assert.IsTrue(policy.RedeliveryDelay(2) == 9, "redelivery delay not 20 is " + policy.RedeliveryDelay(2));
+            Assert.IsTrue(policy.RedeliveryDelay(3) == 27, "redelivery delay not 40 is " + policy.RedeliveryDelay(3));
+            Assert.IsTrue(policy.RedeliveryDelay(4) == 81, "redelivery delay not 80 is " + policy.RedeliveryDelay(4));
+            Assert.IsTrue(policy.RedeliveryDelay(5) == 243, "redelivery delay not 160 is " + policy.RedeliveryDelay(5));
+            Assert.IsTrue(policy.RedeliveryDelay(6) == 729, "redelivery delay not 320 is " + policy.RedeliveryDelay(6));
+            Assert.IsTrue(policy.RedeliveryDelay(7) == 2187, "redelivery delay not 640 is " + policy.RedeliveryDelay(7));
+            Assert.IsTrue(policy.RedeliveryDelay(8) == 6561, "redelivery delay not 1280 is " + policy.RedeliveryDelay(8));
+            Assert.IsTrue(policy.RedeliveryDelay(9) == 19683, "redelivery delay not 2560 is " + policy.RedeliveryDelay(9));
+        }
+
+        [Test]
+        public void Executes_redelivery_policy_without_backoff_enabled_correctly()
+        {
+            RedeliveryPolicy policy = new RedeliveryPolicy();
+
+            policy.InitialRedeliveryDelay = 5;
+
+            // simulate a retry of 10 times
+            Assert.IsTrue(policy.RedeliveryDelay(0) == 0, "redelivery delay not 0 is " + policy.RedeliveryDelay(0));
+            Assert.IsTrue(policy.RedeliveryDelay(1) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(1));
+            Assert.IsTrue(policy.RedeliveryDelay(2) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(2));
+            Assert.IsTrue(policy.RedeliveryDelay(3) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(3));
+            Assert.IsTrue(policy.RedeliveryDelay(4) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(4));
+            Assert.IsTrue(policy.RedeliveryDelay(5) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(5));
+            Assert.IsTrue(policy.RedeliveryDelay(6) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(6));
+            Assert.IsTrue(policy.RedeliveryDelay(7) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(7));
+            Assert.IsTrue(policy.RedeliveryDelay(8) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(8));
+            Assert.IsTrue(policy.RedeliveryDelay(9) == 5, "redelivery delay not 5 is " + policy.RedeliveryDelay(9));
+        }
+
+        [Test]
+        public void Should_get_collision_percent_correctly()
+        {
+            RedeliveryPolicy policy = new RedeliveryPolicy();
+
+            policy.CollisionAvoidancePercent = 45;
+
+            Assert.IsTrue(policy.CollisionAvoidancePercent == 45);
+        }
+
+        [Test]
+        public void Executes_redelivery_policy_with_collision_enabled_correctly()
+        {
+            RedeliveryPolicy policy = new RedeliveryPolicy();
+
+            policy.BackOffMultiplier = 2;
+            policy.InitialRedeliveryDelay = 5;
+            policy.UseExponentialBackOff = true;
+            policy.UseCollisionAvoidance = true;
+            policy.CollisionAvoidancePercent = 10;
+
+            // simulate a retry of 10 times
+            int delay = policy.RedeliveryDelay(0);
+            Assert.IsTrue(delay == 0, "not zero is " + policy.RedeliveryDelay(0));
+            delay = policy.RedeliveryDelay(1);
+            Assert.IsTrue(delay >= 4.5 && delay <= 5.5, "not delay >= 4.5 && delay <= 5.5 is " + policy.RedeliveryDelay(1));
+            delay = policy.RedeliveryDelay(2);
+            Assert.IsTrue(delay >= 9 && delay <= 11, "not delay >= 9 && delay <= 11 is " + policy.RedeliveryDelay(2));
+            delay = policy.RedeliveryDelay(3);
+            Assert.IsTrue(delay >= 18 && delay <= 22, "not delay >= 18 && delay <= 22 is " + policy.RedeliveryDelay(3));
+            delay = policy.RedeliveryDelay(4);
+            Assert.IsTrue(delay >= 36 && delay <= 44, "not delay >= 36 && delay <= 44 is " + policy.RedeliveryDelay(4));
+            delay = policy.RedeliveryDelay(5);
+            Assert.IsTrue(delay >= 72 && delay <= 88, "not delay >= 72 && delay <= 88 is " + policy.RedeliveryDelay(5));
+            delay = policy.RedeliveryDelay(6);
+            Assert.IsTrue(delay >= 144 && delay <= 176, "not delay >= 144 && delay <= 176 is " + policy.RedeliveryDelay(6));
+            delay = policy.RedeliveryDelay(7);
+            Assert.IsTrue(delay >= 288 && delay <= 352, "not delay >= 288 && delay <= 352 is " + policy.RedeliveryDelay(7));
+            delay = policy.RedeliveryDelay(8);
+            Assert.IsTrue(delay >= 576 && delay <= 704, "not delay >= 576 && delay <= 704 is " + policy.RedeliveryDelay(8));
+            delay = policy.RedeliveryDelay(9);
+            Assert.IsTrue(delay >= 1152 && delay <= 1408, "not delay >= 1152 && delay <= 1408 is " + policy.RedeliveryDelay(9));
+            delay = policy.RedeliveryDelay(10);
+            Assert.IsTrue(delay >= 2304 && delay <= 2816, "not delay >= 2304 && delay <= 2816 is " + policy.RedeliveryDelay(10));
+        }
+    }
+}
diff --git a/src/test/csharp/RequestResponseTest.cs b/src/test/csharp/RequestResponseTest.cs
new file mode 100644
index 0000000..d6f0489
--- /dev/null
+++ b/src/test/csharp/RequestResponseTest.cs
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class RequestResponseTest : NMSTest
+	{
+		protected RequestResponseTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		//[Category("RequestResponse")]		
+		public virtual void TestRequestResponseMessaging(string testDestRef, string testRespDestRef)
+		{
+			using(IConnection connection = CreateConnection())
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					IDestination replyTo = GetClearDestinationByNodeReference(session, testRespDestRef);
+
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						IMessage request = session.CreateMessage();
+						
+						request.NMSReplyTo = replyTo;
+						
+						producer.Send(request);
+						
+						request = consumer.Receive(TimeSpan.FromMilliseconds(3000));
+						Assert.IsNotNull(request);
+						Assert.IsNotNull(request.NMSReplyTo);
+						
+						using(IMessageProducer responder = session.CreateProducer(request.NMSReplyTo))
+						{
+							IMessage response = session.CreateTextMessage("RESPONSE");							
+							responder.Send(response);
+						}						
+					}
+					
+					using(IMessageConsumer consumer = session.CreateConsumer(replyTo))
+					{
+						ITextMessage response = consumer.Receive(TimeSpan.FromMilliseconds(3000)) as ITextMessage;
+						Assert.IsNotNull(response);
+						Assert.AreEqual("RESPONSE", response.Text);
+					}
+				}
+			}
+		}
+	}
+}
+
diff --git a/src/test/csharp/StreamMessageTest.cs b/src/test/csharp/StreamMessageTest.cs
new file mode 100644
index 0000000..be690a4
--- /dev/null
+++ b/src/test/csharp/StreamMessageTest.cs
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class StreamMessageTest : NMSTest
+	{
+		protected bool a = true;
+		protected byte b = 123;
+		protected char c = 'c';
+		protected short d = 0x1234;
+		protected int e = 0x12345678;
+		protected long f = 0x1234567812345678;
+		protected string g = "Hello World!";
+		protected bool h = false;
+		protected byte i = 0xFF;
+		protected short j = -0x1234;
+		protected int k = -0x12345678;
+		protected long l = -0x1234567812345678;
+		protected float m = 2.1F;
+		protected double n = 2.3;
+
+		protected StreamMessageTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void TestSendReceiveStreamMessage(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						IStreamMessage request;
+
+						try
+						{
+							request = session.CreateStreamMessage();
+						}
+						catch(System.NotSupportedException)
+						{
+							return;
+						}
+
+						request.WriteBoolean(a);
+						request.WriteByte(b);
+						request.WriteChar(c);
+						request.WriteInt16(d);
+						request.WriteInt32(e);
+						request.WriteInt64(f);
+						request.WriteString(g);
+						request.WriteBoolean(h);
+						request.WriteByte(i);
+						request.WriteInt16(j);
+						request.WriteInt32(k);
+						request.WriteInt64(l);
+						request.WriteSingle(m);
+						request.WriteDouble(n);
+						producer.Send(request);
+
+						IStreamMessage message = consumer.Receive(receiveTimeout) as IStreamMessage;
+						Assert.IsNotNull(message, "No message returned!");
+						Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+
+						// use generic API to access entries
+						Assert.AreEqual(a, message.ReadBoolean(), "Stream Boolean Value: a");
+						Assert.AreEqual(b, message.ReadByte(), "Stream Byte Value: b");
+						Assert.AreEqual(c, message.ReadChar(), "Stream Char Value: c");
+						Assert.AreEqual(d, message.ReadInt16(), "Stream Int16 Value: d");
+						Assert.AreEqual(e, message.ReadInt32(), "Stream Int32 Value: e");
+						Assert.AreEqual(f, message.ReadInt64(), "Stream Int64 Value: f");
+						Assert.AreEqual(g, message.ReadString(), "Stream String Value: g");
+						Assert.AreEqual(h, message.ReadBoolean(), "Stream Boolean Value: h");
+						Assert.AreEqual(i, message.ReadByte(), "Stream Byte Value: i");
+						Assert.AreEqual(j, message.ReadInt16(), "Stream Int16 Value: j");
+						Assert.AreEqual(k, message.ReadInt32(), "Stream Int32 Value: k");
+						Assert.AreEqual(l, message.ReadInt64(), "Stream Int64 Value: l");
+						Assert.AreEqual(m, message.ReadSingle(), "Stream Single Value: m");
+						Assert.AreEqual(n, message.ReadDouble(), "Stream Double Value: n");
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/test/csharp/TempDestinationDeletionTest.cs b/src/test/csharp/TempDestinationDeletionTest.cs
new file mode 100644
index 0000000..834193e
--- /dev/null
+++ b/src/test/csharp/TempDestinationDeletionTest.cs
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class TempDestinationDeletionTest : NMSTest
+	{
+		protected TempDestinationDeletionTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void TestTempDestinationDeletion(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode,
+			//[Values(DELETION_TEST_QUEUE, DELETION_TEST_TOPIC, DELETION_TEST_TEMP_QUEUE, DELETION_TEST_TEMP_TOPIC)]
+			string testDestRef)
+		{
+			using(IConnection connection1 = CreateConnection(GetTestClientId()))
+			{
+				connection1.Start();
+				using(ISession session = connection1.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					const int MaxNumDestinations = 100;
+
+					for(int index = 1; index <= MaxNumDestinations; index++)
+					{
+						IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+
+						using(IMessageProducer producer = session.CreateProducer(destination))
+						using(IMessageConsumer consumer = session.CreateConsumer(destination))
+						{
+							producer.DeliveryMode = deliveryMode;
+
+							IMessage request = session.CreateTextMessage("Hello World, Just Passing Through!");
+
+							request.NMSType = "TEMP_MSG";
+							producer.Send(request);
+							IMessage receivedMsg = consumer.Receive(TimeSpan.FromMilliseconds(5000));
+							Assert.IsNotNull(receivedMsg);
+							Assert.AreEqual(receivedMsg.NMSType, "TEMP_MSG");
+							
+							// Ensures that Consumer closes out its subscription
+							consumer.Close();
+						}
+
+						try
+						{
+							session.DeleteDestination(destination);
+						}
+						catch(NotSupportedException)
+						{
+							// Might as well not try this again.
+							break;
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/test/csharp/TempDestinationTest.cs b/src/test/csharp/TempDestinationTest.cs
new file mode 100644
index 0000000..b9a75e4
--- /dev/null
+++ b/src/test/csharp/TempDestinationTest.cs
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+    //[TestFixture]
+    public class TempDestinationTest : NMSTest
+    {
+        private IConnection connection;
+        private IList connections = ArrayList.Synchronized(new ArrayList());
+
+		protected TempDestinationTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+        //[SetUp]
+        public override void SetUp()
+        {
+            base.SetUp();
+
+            this.connection = CreateConnection();
+            this.connections.Add(connection);
+        }
+
+        //[TearDown]
+        public override void TearDown()
+        {
+            foreach(IConnection conn in this.connections)
+            {
+                try
+                {
+                    conn.Close();
+                }
+                catch
+                {
+                }
+            }
+
+            connections.Clear();
+
+            base.TearDown();
+        }
+
+        //[Test]
+        public virtual void TestTempDestOnlyConsumedByLocalConn()
+        {
+            connection.Start();
+
+            ISession tempSession = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+            ITemporaryQueue queue = tempSession.CreateTemporaryQueue();
+            IMessageProducer producer = tempSession.CreateProducer(queue);
+            producer.DeliveryMode = (MsgDeliveryMode.NonPersistent);
+            ITextMessage message = tempSession.CreateTextMessage("First");
+            producer.Send(message);
+
+            // temp destination should not be consume when using another connection
+            IConnection otherConnection = CreateConnection();
+            connections.Add(otherConnection);
+            ISession otherSession = otherConnection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+            ITemporaryQueue otherQueue = otherSession.CreateTemporaryQueue();
+            IMessageConsumer consumer = otherSession.CreateConsumer(otherQueue);
+            IMessage msg = consumer.Receive(TimeSpan.FromMilliseconds(3000));
+            Assert.IsNull(msg);
+
+            // should be able to consume temp destination from the same connection
+            consumer = tempSession.CreateConsumer(queue);
+            msg = consumer.Receive(TimeSpan.FromMilliseconds(3000));
+            Assert.IsNotNull(msg);
+        }
+
+        //[Test]
+        public virtual void TestTempQueueHoldsMessagesWithConsumers()
+        {
+            ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+            ITemporaryQueue queue = session.CreateTemporaryQueue();
+            IMessageConsumer consumer = session.CreateConsumer(queue);
+            connection.Start();
+
+            IMessageProducer producer = session.CreateProducer(queue);
+            producer.DeliveryMode = (MsgDeliveryMode.NonPersistent);
+            ITextMessage message = session.CreateTextMessage("Hello");
+            producer.Send(message);
+
+            IMessage message2 = consumer.Receive(TimeSpan.FromMilliseconds(1000));
+            Assert.IsNotNull(message2);
+            Assert.IsTrue(message2 is ITextMessage, "Expected message to be a ITextMessage");
+            Assert.IsTrue(((ITextMessage)message2).Text == message.Text, "Expected message to be a '" + message.Text + "'");
+        }
+
+        //[Test]
+        public virtual void TestTempQueueHoldsMessagesWithoutConsumers()
+        {
+            ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+            ITemporaryQueue queue = session.CreateTemporaryQueue();
+            IMessageProducer producer = session.CreateProducer(queue);
+            producer.DeliveryMode = MsgDeliveryMode.NonPersistent;
+            ITextMessage message = session.CreateTextMessage("Hello");
+            producer.Send(message);
+
+            connection.Start();
+            IMessageConsumer consumer = session.CreateConsumer(queue);
+            IMessage message2 = consumer.Receive(TimeSpan.FromMilliseconds(3000));
+            Assert.IsNotNull(message2);
+            Assert.IsTrue(message2 is ITextMessage, "Expected message to be a ITextMessage");
+            Assert.IsTrue(((ITextMessage)message2).Text == message.Text, "Expected message to be a '" + message.Text + "'");
+        }
+
+        //[Test]
+        public virtual void TestTmpQueueWorksUnderLoad()
+        {
+            int count = 500;
+            int dataSize = 1024;
+
+            ArrayList list = new ArrayList(count);
+            ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+            ITemporaryQueue queue = session.CreateTemporaryQueue();
+            IBytesMessage message;
+            IBytesMessage message2;
+            IMessageProducer producer = session.CreateProducer(queue);
+            producer.DeliveryMode = MsgDeliveryMode.NonPersistent;
+
+            byte[] srcdata = new byte[dataSize];
+            srcdata[0] = (byte) 'B';
+            srcdata[1] = (byte) 'A';
+            srcdata[2] = (byte) 'D';
+            srcdata[3] = (byte) 'W';
+            srcdata[4] = (byte) 'O';
+            srcdata[5] = (byte) 'L';
+            srcdata[6] = (byte) 'F';
+            for(int i = 0; i < count; i++)
+            {
+                message = session.CreateBytesMessage();
+                message.WriteBytes(srcdata);
+                message.Properties.SetInt("c", i);
+                producer.Send(message);
+                list.Add(message);
+            }
+
+            connection.Start();
+            byte[] data = new byte[dataSize];
+            byte[] data2 = new byte[dataSize];
+            IMessageConsumer consumer = session.CreateConsumer(queue);
+            for(int i = 0; i < count; i++)
+            {
+                message2 = consumer.Receive(TimeSpan.FromMilliseconds(2000)) as IBytesMessage;
+                Assert.IsNotNull(message2);
+                Assert.AreEqual(i, message2.Properties.GetInt("c"));
+                message = list[i] as IBytesMessage;
+                Assert.IsNotNull(message);
+				message.Reset();
+                message.ReadBytes(data);
+                message2.ReadBytes(data2);
+                Assert.AreEqual(data, data2);
+            }
+        }
+    }
+}
diff --git a/src/test/csharp/TextMessageTest.cs b/src/test/csharp/TextMessageTest.cs
new file mode 100644
index 0000000..a5f23fd
--- /dev/null
+++ b/src/test/csharp/TextMessageTest.cs
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class TextMessageTest : NMSTest
+	{
+		protected TextMessageTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void TestSendReceiveTextMessage(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						IMessage request = session.CreateTextMessage("Hello World!");
+						producer.Send(request);
+
+						IMessage message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(request, message);
+						Assert.AreEqual(deliveryMode, message.NMSDeliveryMode, "NMSDeliveryMode does not match");
+					}
+				}
+			}
+		}
+
+		/// <summary>
+		/// Assert that two messages are ITextMessages and their text bodies are equal.
+		/// </summary>
+		/// <param name="expected"></param>
+		/// <param name="actual"></param>
+		protected void AssertTextMessageEqual(IMessage expected, IMessage actual)
+		{
+			ITextMessage expectedTextMsg = expected as ITextMessage;
+			Assert.IsNotNull(expectedTextMsg, "'expected' message not a text message");
+			ITextMessage actualTextMsg = actual as ITextMessage;
+			Assert.IsNotNull(actualTextMsg, "'actual' message not a text message");
+			Assert.AreEqual(expectedTextMsg.Text, actualTextMsg.Text, "Text message does not match.");
+		}
+	}
+}
diff --git a/src/test/csharp/TransactionTest.cs b/src/test/csharp/TransactionTest.cs
new file mode 100644
index 0000000..8fd7f93
--- /dev/null
+++ b/src/test/csharp/TransactionTest.cs
@@ -0,0 +1,439 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	//[TestFixture]
+	public class TransactionTest : NMSTest
+	{
+		protected TransactionTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+		//[Test]
+		public virtual void TestSendRollback(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.Transactional))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						ITextMessage firstMsgSend = session.CreateTextMessage("First Message");
+						producer.Send(firstMsgSend);
+						session.Commit();
+
+						ITextMessage rollbackMsg = session.CreateTextMessage("I'm going to get rolled back.");
+						producer.Send(rollbackMsg);
+						session.Rollback();
+
+						ITextMessage secondMsgSend = session.CreateTextMessage("Second Message");
+						producer.Send(secondMsgSend);
+						session.Commit();
+
+						// Receive the messages
+
+						IMessage message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(firstMsgSend, message, "First message does not match.");
+
+						message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(secondMsgSend, message, "Second message does not match.");
+
+						// validates that the rollback was not consumed
+						session.Commit();
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestSendSessionClose(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			ITextMessage firstMsgSend;
+			ITextMessage secondMsgSend;
+
+			using(IConnection connection1 = CreateConnection(GetTestClientId()))
+			{
+				connection1.Start();
+				using(ISession session1 = connection1.CreateSession(AcknowledgementMode.Transactional))
+				{
+					IDestination destination1 = GetClearDestinationByNodeReference(session1, testDestRef);
+					using(IMessageConsumer consumer = session1.CreateConsumer(destination1))
+					{
+						// First connection session that sends one message, and the
+						// second message is implicitly rolled back as the session is
+						// disposed before Commit() can be called.
+						using(IConnection connection2 = CreateConnection(GetTestClientId()))
+						{
+							connection2.Start();
+							using(ISession session2 = connection2.CreateSession(AcknowledgementMode.Transactional))
+							{
+								IDestination destination2 = GetClearDestinationByNodeReference(session2, testDestRef);
+								using(IMessageProducer producer = session2.CreateProducer(destination2))
+								{
+									producer.DeliveryMode = deliveryMode;
+									firstMsgSend = session2.CreateTextMessage("First Message");
+									producer.Send(firstMsgSend);
+									session2.Commit();
+
+									ITextMessage rollbackMsg = session2.CreateTextMessage("I'm going to get rolled back.");
+									producer.Send(rollbackMsg);
+								}
+							}
+						}
+
+						// Second connection session that will send one message.
+						using(IConnection connection2 = CreateConnection(GetTestClientId()))
+						{
+							connection2.Start();
+							using(ISession session2 = connection2.CreateSession(AcknowledgementMode.Transactional))
+							{
+								IDestination destination2 = GetClearDestinationByNodeReference(session2, testDestRef);
+								using(IMessageProducer producer = session2.CreateProducer(destination2))
+								{
+									producer.DeliveryMode = deliveryMode;
+									secondMsgSend = session2.CreateTextMessage("Second Message");
+									producer.Send(secondMsgSend);
+									session2.Commit();
+								}
+							}
+						}
+
+						// Check the consumer to verify which messages were actually received.
+						IMessage message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(firstMsgSend, message, "First message does not match.");
+
+						message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(secondMsgSend, message, "Second message does not match.");
+
+						// validates that the rollback was not consumed
+						session1.Commit();
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestReceiveRollback(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.Transactional))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						// Send both messages
+						ITextMessage firstMsgSend = session.CreateTextMessage("First Message");
+						producer.Send(firstMsgSend);
+						ITextMessage secondMsgSend = session.CreateTextMessage("Second Message");
+						producer.Send(secondMsgSend);
+						session.Commit();
+
+						// Receive the messages
+
+						IMessage message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(firstMsgSend, message, "First message does not match.");
+						session.Commit();
+
+						message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(secondMsgSend, message, "Second message does not match.");
+
+						// Rollback so we can get that last message again.
+						session.Rollback();
+						IMessage rollbackMsg = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(secondMsgSend, rollbackMsg, "Rollback message does not match.");
+						session.Commit();
+					}
+				}
+			}
+		}
+
+
+		//[Test]
+		public virtual void TestReceiveTwoThenRollback(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.Transactional))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						// Send both messages
+						ITextMessage firstMsgSend = session.CreateTextMessage("First Message");
+						producer.Send(firstMsgSend);
+						ITextMessage secondMsgSend = session.CreateTextMessage("Second Message");
+						producer.Send(secondMsgSend);
+						session.Commit();
+
+						// Receive the messages
+
+						IMessage message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(firstMsgSend, message, "First message does not match.");
+						message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(secondMsgSend, message, "Second message does not match.");
+
+						// Rollback so we can get that last two messages again.
+						session.Rollback();
+						IMessage rollbackMsg = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(firstMsgSend, rollbackMsg, "First rollback message does not match.");
+						rollbackMsg = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(secondMsgSend, rollbackMsg, "Second rollback message does not match.");
+
+						Assert.IsNull(consumer.ReceiveNoWait());
+						session.Commit();
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestSendCommitNonTransaction(
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge)]
+			AcknowledgementMode ackMode,
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(ackMode))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						ITextMessage firstMsgSend = session.CreateTextMessage("SendCommitNonTransaction Message");
+						producer.Send(firstMsgSend);
+						try
+						{
+							session.Commit();
+							Assert.Fail("Should have thrown an InvalidOperationException.");
+						}
+						catch(InvalidOperationException)
+						{
+						}
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestReceiveCommitNonTransaction(
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge)]
+			AcknowledgementMode ackMode,
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(ackMode))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						ITextMessage firstMsgSend = session.CreateTextMessage("ReceiveCommitNonTransaction Message");
+						producer.Send(firstMsgSend);
+
+						// Receive the messages
+
+						IMessage message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(firstMsgSend, message, "First message does not match.");
+						if(AcknowledgementMode.ClientAcknowledge == ackMode)
+						{
+							message.Acknowledge();
+						}
+
+						try
+						{
+							session.Commit();
+							Assert.Fail("Should have thrown an InvalidOperationException.");
+						}
+						catch(InvalidOperationException)
+						{
+						}
+					}
+				}
+			}
+		}
+
+		//[Test]
+		public virtual void TestReceiveRollbackNonTransaction(
+			//[Values(AcknowledgementMode.AutoAcknowledge, AcknowledgementMode.ClientAcknowledge)]
+			AcknowledgementMode ackMode,
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(ackMode))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						producer.DeliveryMode = deliveryMode;
+						ITextMessage firstMsgSend = session.CreateTextMessage("ReceiveCommitNonTransaction Message");
+						producer.Send(firstMsgSend);
+
+						// Receive the messages
+
+						IMessage message = consumer.Receive(receiveTimeout);
+						AssertTextMessageEqual(firstMsgSend, message, "First message does not match.");
+						if(AcknowledgementMode.ClientAcknowledge == ackMode)
+						{
+							message.Acknowledge();
+						}
+
+						try
+						{
+							session.Rollback();
+							Assert.Fail("Should have thrown an InvalidOperationException.");
+						}
+						catch(InvalidOperationException)
+						{
+						}
+					}
+				}
+			}
+		}
+
+		/// <summary>
+		/// Assert that two messages are ITextMessages and their text bodies are equal.
+		/// </summary>
+		/// <param name="expected"></param>
+		/// <param name="actual"></param>
+		/// <param name="message"></param>
+		protected void AssertTextMessageEqual(IMessage expected, IMessage actual, String message)
+		{
+			ITextMessage expectedTextMsg = expected as ITextMessage;
+			Assert.IsNotNull(expectedTextMsg, "'expected' message not a text message");
+			ITextMessage actualTextMsg = actual as ITextMessage;
+			Assert.IsNotNull(actualTextMsg, "'actual' message not a text message");
+			Assert.AreEqual(expectedTextMsg.Text, actualTextMsg.Text, message);
+		}
+
+		//[Test]
+		public virtual void TestRedispatchOfRolledbackTx(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				ISession session = connection.CreateSession(AcknowledgementMode.Transactional);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+
+				SendMessages(connection, destination, deliveryMode, 2);
+
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+				Assert.IsNotNull(consumer.Receive(TimeSpan.FromMilliseconds(1500)));
+				Assert.IsNotNull(consumer.Receive(TimeSpan.FromMilliseconds(1500)));
+
+				// install another consumer while message dispatch is unacked/uncommitted
+				ISession redispatchSession = connection.CreateSession(AcknowledgementMode.Transactional);
+				IMessageConsumer redispatchConsumer = redispatchSession.CreateConsumer(destination);
+
+				session.Rollback();
+				session.Close();
+
+				IMessage msg = redispatchConsumer.Receive(TimeSpan.FromMilliseconds(1500));
+				Assert.IsNotNull(msg);
+				Assert.IsTrue(msg.NMSRedelivered);
+				Assert.AreEqual(2, msg.Properties.GetLong("NMSXDeliveryCount"));
+				msg = redispatchConsumer.Receive(TimeSpan.FromMilliseconds(1500));
+				Assert.IsNotNull(msg);
+				Assert.IsTrue(msg.NMSRedelivered);
+				Assert.AreEqual(2, msg.Properties.GetLong("NMSXDeliveryCount"));
+				redispatchSession.Commit();
+
+				Assert.IsNull(redispatchConsumer.Receive(TimeSpan.FromMilliseconds(500)));
+				redispatchSession.Close();
+			}
+		}
+
+		//[Test]
+		public virtual void TestRedispatchOfUncommittedTx(
+			//[Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+			MsgDeliveryMode deliveryMode, string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				ISession session = connection.CreateSession(AcknowledgementMode.Transactional);
+				IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+
+				SendMessages(connection, destination, deliveryMode, 2);
+
+				IMessageConsumer consumer = session.CreateConsumer(destination);
+				Assert.IsNotNull(consumer.Receive(TimeSpan.FromMilliseconds(2000)));
+				Assert.IsNotNull(consumer.Receive(TimeSpan.FromMilliseconds(2000)));
+
+				// install another consumer while message dispatch is unacked/uncommitted
+				ISession redispatchSession = connection.CreateSession(AcknowledgementMode.Transactional);
+				IMessageConsumer redispatchConsumer = redispatchSession.CreateConsumer(destination);
+
+				// no commit so will auto rollback and get re-dispatched to redisptachConsumer
+				session.Close();
+
+				IMessage msg = redispatchConsumer.Receive(TimeSpan.FromMilliseconds(2000));
+				Assert.IsNotNull(msg);
+				Assert.IsTrue(msg.NMSRedelivered);
+				Assert.AreEqual(2, msg.Properties.GetLong("NMSXDeliveryCount"));
+
+				msg = redispatchConsumer.Receive(TimeSpan.FromMilliseconds(2000));
+				Assert.IsNotNull(msg);
+				Assert.IsTrue(msg.NMSRedelivered);
+				Assert.AreEqual(2, msg.Properties.GetLong("NMSXDeliveryCount"));
+				redispatchSession.Commit();
+
+				Assert.IsNull(redispatchConsumer.Receive(TimeSpan.FromMilliseconds(500)));
+				redispatchSession.Close();
+			}
+		}
+	}
+}
+
+
diff --git a/src/test/csharp/XmlMessageTest.cs b/src/test/csharp/XmlMessageTest.cs
new file mode 100644
index 0000000..9c9fc88
--- /dev/null
+++ b/src/test/csharp/XmlMessageTest.cs
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+	// For ease of cross-platform exchange of information, you might generate objects from
+	// an XSD file using XSDObjectGen. However, C# has built-in support for serializing.
+	// All of the XML attributes that are commented out are optional, but give you fine-grained
+	// control over the serialized format if you need it.
+
+	// [Serializable]
+	public enum CheckType
+	{
+		// [XmlEnum(Name = "message")]
+		message,
+		// [XmlEnum(Name = "command")]
+		command,
+		// [XmlEnum(Name = "response")]
+		response
+	}
+
+	// [XmlRoot(ElementName = "NMSTestXmlType1", IsNullable = false), Serializable]
+	public class NMSTestXmlType1
+	{
+		// [XmlElement(ElementName = "crcCheck", IsNullable = false, DataType = "int")]
+		public int crcCheck;
+
+		// [XmlElement(Type = typeof(CheckType), ElementName = "checkType", IsNullable = false)]
+		public CheckType checkType;
+
+		public NMSTestXmlType1()
+		{
+			crcCheck = 0;
+			checkType = CheckType.message;
+		}
+	}
+
+	// [XmlRoot(ElementName = "NMSTestXmlType2", IsNullable = false), Serializable]
+	public class NMSTestXmlType2
+	{
+		// [XmlElement(ElementName = "stringCheck", IsNullable = false, DataType = "string")]
+		public string stringCheck;
+
+		public NMSTestXmlType2()
+		{
+			stringCheck = String.Empty;
+		}
+	}
+
+	//[TestFixture]
+	public class XmlMessageTest : NMSTest
+	{
+		public XmlMessageTest(NMSTestSupport testSupport)
+			: base(testSupport)
+		{
+		}
+
+#if NET_3_5 || MONO
+
+		//[Test]
+		public virtual void TestSendReceiveXmlMessage_Net35(string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						NMSTestXmlType1 srcIntObject = new NMSTestXmlType1();
+						srcIntObject.crcCheck = 0xbadf00d;
+						srcIntObject.checkType = CheckType.command;
+						producer.Send(srcIntObject);
+
+						NMSTestXmlType2 srcStringObject = new NMSTestXmlType2();
+						srcStringObject.stringCheck = "BadFood";
+						producer.Send(srcStringObject);
+
+						// Demonstrate the ability to generically handle multiple object types
+						// sent to the same consumer.  If only one object type is ever sent to
+						// the destination, then a simple inline cast is all that is necessary
+						// when calling the NMSConvert.FromXmlMessage() function.
+
+						for(int index = 0; index < 2; index++)
+						{
+							object receivedObject = consumer.Receive(receiveTimeout).ToObject();
+							Assert.IsNotNull(receivedObject, "Failed to retrieve XML message object.");
+
+							if(receivedObject is NMSTestXmlType1)
+							{
+								NMSTestXmlType1 destObject = (NMSTestXmlType1) receivedObject;
+								Assert.AreEqual(srcIntObject.crcCheck, destObject.crcCheck, "CRC integer mis-match.");
+								Assert.AreEqual(srcIntObject.checkType, destObject.checkType, "Check type mis-match.");
+							}
+							else if(receivedObject is NMSTestXmlType2)
+							{
+								NMSTestXmlType2 destObject = (NMSTestXmlType2) receivedObject;
+								Assert.AreEqual(srcStringObject.stringCheck, destObject.stringCheck, "CRC string mis-match.");
+							}
+							else
+							{
+								Assert.Fail("Invalid object type.");
+							}
+						}
+					}
+				}
+			}
+		}
+
+#else
+
+		// Test the obsolete API versions until they are completely removed.
+		//[Test]
+		public virtual void TestSendReceiveXmlMessage(string testDestRef)
+		{
+			using(IConnection connection = CreateConnection(GetTestClientId()))
+			{
+				connection.Start();
+				using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+				{
+					IDestination destination = GetClearDestinationByNodeReference(session, testDestRef);
+					using(IMessageConsumer consumer = session.CreateConsumer(destination))
+					using(IMessageProducer producer = session.CreateProducer(destination))
+					{
+						NMSTestXmlType1 srcIntObject = new NMSTestXmlType1();
+						srcIntObject.crcCheck = 0xbadf00d;
+						srcIntObject.checkType = CheckType.command;
+						producer.Send(NMSConvert.ToXmlMessage(session, srcIntObject));
+
+						NMSTestXmlType2 srcStringObject = new NMSTestXmlType2();
+						srcStringObject.stringCheck = "BadFood";
+						producer.Send(NMSConvert.ToXmlMessage(session, srcStringObject));
+
+						// Demonstrate the ability to generically handle multiple object types
+						// sent to the same consumer.  If only one object type is ever sent to
+						// the destination, then a simple inline cast is all that is necessary
+						// when calling the NMSConvert.FromXmlMessage() function.
+
+						for(int index = 0; index < 2; index++)
+						{
+							object receivedObject = NMSConvert.FromXmlMessage(consumer.Receive(receiveTimeout));
+							Assert.IsNotNull(receivedObject, "Failed to retrieve XML message object.");
+
+							if(receivedObject is NMSTestXmlType1)
+							{
+								NMSTestXmlType1 destObject = (NMSTestXmlType1) receivedObject;
+								Assert.AreEqual(srcIntObject.crcCheck, destObject.crcCheck, "CRC integer mis-match.");
+								Assert.AreEqual(srcIntObject.checkType, destObject.checkType, "Check type mis-match.");
+							}
+							else if(receivedObject is NMSTestXmlType2)
+							{
+								NMSTestXmlType2 destObject = (NMSTestXmlType2) receivedObject;
+								Assert.AreEqual(srcStringObject.stringCheck, destObject.stringCheck, "CRC string mis-match.");
+							}
+							else
+							{
+								Assert.Fail("Invalid object type.");
+							}
+						}
+					}
+				}
+			}
+		}
+
+#endif
+	}
+}
diff --git a/vs2008-msmq-test.csproj b/vs2008-msmq-test.csproj
index 685f1fc..e330436 100644
--- a/vs2008-msmq-test.csproj
+++ b/vs2008-msmq-test.csproj
@@ -1,9 +1,8 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProductVersion>9.0.30729</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{2F31ED5C-44A2-464A-BD55-2B5B010654E8}</ProjectGuid>
     <OutputType>Library</OutputType>
     <RootNamespace>Apache.NMS.MSMQ.Test</RootNamespace>
@@ -79,6 +78,67 @@
     <Compile Include="src\test\csharp\MSMQTest.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="src\test\csharp\AsyncConsumeTest.cs" />
+    <Compile Include="src\test\csharp\BadConsumeTest.cs" />
+    <Compile Include="src\test\csharp\BytesMessageTest.cs" />
+    <Compile Include="src\test\csharp\ConnectionTest.cs" />
+    <Compile Include="src\test\csharp\ConsumerTest.cs" />
+    <Compile Include="src\test\csharp\DurableTest.cs" />
+    <Compile Include="src\test\csharp\EndianBinaryReaderTest.cs" />
+    <Compile Include="src\test\csharp\EndianBinaryWriterTest.cs" />
+    <Compile Include="src\test\csharp\EndianTest.cs" />
+    <Compile Include="src\test\csharp\ForeignMessageTransformationTest.cs" />
+    <Compile Include="src\test\csharp\MapMessageTest.cs" />
+    <Compile Include="src\test\csharp\MessageSelectorTest.cs" />
+    <Compile Include="src\test\csharp\MessageTest.cs" />
+    <Compile Include="src\test\csharp\MessageTransformerTest.cs" />
+    <Compile Include="src\test\csharp\MSMQAsyncConsumeTest.cs" />
+    <Compile Include="src\test\csharp\MSMQBadConsumeTest.cs" />
+    <Compile Include="src\test\csharp\MSMQBytesMessageTest.cs" />
+    <Compile Include="src\test\csharp\MSMQConnectionTest.cs" />
+    <Compile Include="src\test\csharp\MSMQConsumerTest.cs" />
+    <Compile Include="src\test\csharp\MSMQDurableTest.cs" />
+    <Compile Include="src\test\csharp\MSMQForeignMessageTransformationTest.cs" />
+    <Compile Include="src\test\csharp\MSMQMapMessageTest.cs" />
+    <Compile Include="src\test\csharp\MSMQMessageSelectorTest.cs" />
+    <Compile Include="src\test\csharp\MSMQMessageTest.cs" />
+    <Compile Include="src\test\csharp\MSMQMessageTransformerTest.cs" />
+    <Compile Include="src\test\csharp\MSMQNMSPropertyTest.cs" />
+    <Compile Include="src\test\csharp\MSMQProducerTest.cs" />
+    <Compile Include="src\test\csharp\MSMQRequestResponseTest.cs" />
+    <Compile Include="src\test\csharp\MSMQStreamMessageTest.cs" />
+    <Compile Include="src\test\csharp\MSMQTempDestinationDeletionTest.cs" />
+    <Compile Include="src\test\csharp\MSMQTempDestinationTest.cs" />
+    <Compile Include="src\test\csharp\MSMQTestSupport.cs" />
+    <Compile Include="src\test\csharp\MSMQTextMessageTest.cs" />
+    <Compile Include="src\test\csharp\MSMQTransactionTest.cs" />
+    <Compile Include="src\test\csharp\MSMQXmlMessageTest.cs" />
+    <Compile Include="src\test\csharp\NMSPropertyTest.cs" />
+    <Compile Include="src\test\csharp\NMSTest.cs" />
+    <Compile Include="src\test\csharp\NMSTestSupport.cs" />
+    <Compile Include="src\test\csharp\NMSTracer.cs" />
+    <Compile Include="src\test\csharp\PrimitiveMapTest.cs" />
+    <Compile Include="src\test\csharp\ProducerTest.cs" />
+    <Compile Include="src\test\csharp\RedeliveryPolicyTest.cs" />
+    <Compile Include="src\test\csharp\RequestResponseTest.cs" />
+    <Compile Include="src\test\csharp\StreamMessageTest.cs" />
+    <Compile Include="src\test\csharp\TempDestinationDeletionTest.cs" />
+    <Compile Include="src\test\csharp\TempDestinationTest.cs" />
+    <Compile Include="src\test\csharp\TextMessageTest.cs" />
+    <Compile Include="src\test\csharp\TransactionTest.cs" />
+    <Compile Include="src\test\csharp\XmlMessageTest.cs" />
+    <Compile Include="src\test\csharp\Commands\BytesMessage.cs" />
+    <Compile Include="src\test\csharp\Commands\Destination.cs" />
+    <Compile Include="src\test\csharp\Commands\MapMessage.cs" />
+    <Compile Include="src\test\csharp\Commands\Message.cs" />
+    <Compile Include="src\test\csharp\Commands\ObjectMessage.cs" />
+    <Compile Include="src\test\csharp\Commands\Queue.cs" />
+    <Compile Include="src\test\csharp\Commands\StreamMessage.cs" />
+    <Compile Include="src\test\csharp\Commands\TempDestination.cs" />
+    <Compile Include="src\test\csharp\Commands\TempQueue.cs" />
+    <Compile Include="src\test\csharp\Commands\TempTopic.cs" />
+    <Compile Include="src\test\csharp\Commands\TextMessage.cs" />
+    <Compile Include="src\test\csharp\Commands\Topic.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="vs2008-msmq.csproj">
@@ -110,6 +170,7 @@
   </ItemGroup>
   <ItemGroup>
     <None Include="keyfile\NMSKey.snk" />
+    <None Include="msmqprovider-test.config" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
   <PropertyGroup>
diff --git a/vs2008-msmq.csproj b/vs2008-msmq.csproj
index 3023e88..76ab1dc 100644
--- a/vs2008-msmq.csproj
+++ b/vs2008-msmq.csproj
@@ -1,9 +1,8 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProductVersion>9.0.30729</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}</ProjectGuid>
     <OutputType>Library</OutputType>
     <RootNamespace>Apache.NMS.MSMQ</RootNamespace>
diff --git a/vs2008-msmq.sln b/vs2008-msmq.sln
index a51006f..010ea3c 100644
--- a/vs2008-msmq.sln
+++ b/vs2008-msmq.sln
@@ -1,30 +1,30 @@
-

-Microsoft Visual Studio Solution File, Format Version 10.00

-# Visual Studio 2008

-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vs2008-msmq", "vs2008-msmq.csproj", "{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}"

-EndProject

-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vs2008-msmq-test", "vs2008-msmq-test.csproj", "{2F31ED5C-44A2-464A-BD55-2B5B010654E8}"

-EndProject

-Global

-	GlobalSection(SubversionScc) = preSolution

-		Svn-Managed = True

-		Manager = AnkhSVN - Subversion Support for Visual Studio

-	EndGlobalSection

-	GlobalSection(SolutionConfigurationPlatforms) = preSolution

-		Debug|Any CPU = Debug|Any CPU

-		Release|Any CPU = Release|Any CPU

-	EndGlobalSection

-	GlobalSection(ProjectConfigurationPlatforms) = postSolution

-		{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}.Release|Any CPU.Build.0 = Release|Any CPU

-		{2F31ED5C-44A2-464A-BD55-2B5B010654E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{2F31ED5C-44A2-464A-BD55-2B5B010654E8}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{2F31ED5C-44A2-464A-BD55-2B5B010654E8}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{2F31ED5C-44A2-464A-BD55-2B5B010654E8}.Release|Any CPU.Build.0 = Release|Any CPU

-	EndGlobalSection

-	GlobalSection(SolutionProperties) = preSolution

-		HideSolutionNode = FALSE

-	EndGlobalSection

-EndGlobal

+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vs2008-msmq", "vs2008-msmq.csproj", "{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vs2008-msmq-test", "vs2008-msmq-test.csproj", "{2F31ED5C-44A2-464A-BD55-2B5B010654E8}"
+EndProject
+Global
+	GlobalSection(SubversionScc) = preSolution
+		Svn-Managed = True
+		Manager = AnkhSVN - Subversion Support for Visual Studio
+	EndGlobalSection
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A5FCA129-991B-4CB2-987A-B25E43B0F5EC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2F31ED5C-44A2-464A-BD55-2B5B010654E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2F31ED5C-44A2-464A-BD55-2B5B010654E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2F31ED5C-44A2-464A-BD55-2B5B010654E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2F31ED5C-44A2-464A-BD55-2B5B010654E8}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal