context: #if NET_4_0
  //
  // Authors:
  //	David Straw
  //	Atsushi Enomoto <atsushi@ximian.com>
  //
  // Copyright (C) 2011 Novell, Inc.  http://www.novell.com
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  using System;
  using System.Collections.Generic;
  using System.Collections.ObjectModel;
  using System.Linq;
  using System.Runtime.Serialization;
  using System.ServiceModel;
  using System.ServiceModel.Description;
  using System.Threading;
  using NUnit.Framework;
  
  using WebServiceMoonlightTest.ServiceReference2;
  
  using MonoTests.Helpers;
  
  namespace MonoTests.System.ServiceModel.Dispatcher
  {
  	[TestFixture]
  	public class Bug652331_2Test
  	{
  		[Test]
  		[Category ("NotWorking")]
  		public void Bug652331_3 ()
  		{
  			// Init service
  			ServiceHost serviceHost = new ServiceHost(typeof(Service1), new Uri("http://localhost:" + NetworkHelpers.FindFreePort () + "/Service1"));
  			serviceHost.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), string.Empty);
  
  			// Enable metadata exchange (WSDL publishing)
  			ServiceMetadataBehavior mexBehavior = new ServiceMetadataBehavior();
  			mexBehavior.HttpGetEnabled = true;
  			serviceHost.Description.Behaviors.Add(mexBehavior);
  			serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
  
  			serviceHost.Open();
  
  			try {
  				RunClient ();
  			} finally {
  				serviceHost.Close ();
  			}
  		}
  
  		void RunClient ()
  		{
  			var binding = new BasicHttpBinding ();
  			var remoteAddress = new EndpointAddress ("http://localhost:" + NetworkHelpers.FindFreePort () + "/Service1");
  
  			var normalClient      = new Service1Client (binding, remoteAddress);
  			var collectionClient  = new Service1Client (binding, remoteAddress);
  			var nestedClient      = new Service1Client (binding, remoteAddress);
  			var dbClient          = new Service1Client (binding, remoteAddress);
  
  			var waits = new ManualResetEvent [4];
  			for (int i = 0; i < waits.Length; i++)
  				waits [i] = new ManualResetEvent (false);
  
  			int passed = 0;
  
  			normalClient.GetDataCompleted += delegate (object o, GetDataCompletedEventArgs e) {
  				if (e.Error != null) {
  					Assert.Fail ("Normal failed; error: {0}", e.Error);
  					throw e.Error;
  				}
  				Assert.AreEqual ("A", ((DataType1) e.Result).Id, "Normal");
  				Interlocked.Increment (ref passed);
  				waits [0].Set ();
  			};
  			normalClient.GetDataAsync ();
  
  			collectionClient.GetCollectionDataCompleted += delegate (object sender, GetCollectionDataCompletedEventArgs e) {
  				if (e.Error != null) {
  					Assert.Fail ("Collection failed; error: {0}", e.Error);
  					throw e.Error;
  				}
  				Assert.AreEqual ("B,C", ItemsToString (e.Result.Cast<DataType1> ()), "Collection");
  				Interlocked.Increment (ref passed);
  				waits [1].Set ();
  			};
  			collectionClient.GetCollectionDataAsync ();
  
  			nestedClient.GetNestedDataCompleted += delegate (object sender, GetNestedDataCompletedEventArgs e) {
  				if (e.Error != null) {
  					Assert.Fail ("Nested failed; error: {0}", e.Error);
  					throw e.Error;
  				}
  				Assert.AreEqual ("D,E", ItemsToString (e.Result.Items.Cast<DataType1> ()), "Nested");
  				Interlocked.Increment (ref passed);
  				waits [2].Set ();
  			};
  			nestedClient.GetNestedDataAsync ();
  
  			dbClient.JSMGetDatabasesCompleted += delegate (object sender, JSMGetDatabasesCompletedEventArgs e) {
  				waits [3].Set ();
  				if (e.Error != null) {
  					throw e.Error;
  				}
  				Assert.AreEqual ("databases", e.Result, "Databases");
  				Interlocked.Increment (ref passed);
  			};
  			dbClient.JSMGetDatabasesAsync();
  
  			WaitHandle.WaitAll (waits, TimeSpan.FromMinutes (1));
  			if (passed != waits.Length)
  				Assert.Fail ("Not all tests passed!");
  		}
  
  		string ItemsToString (IEnumerable<DataType1> items)
  		{
  			return items.Aggregate ((string) null, (result, item) => result == null ? item.Id : result + "," + item.Id);
  		}
  	}
  
  	public class Service1 : IService1
  	{
  		public object GetData()
  		{
  			return new DataType1 { Id = "A" };
  		}
  
  		Func<object> gd;
  		public IAsyncResult BeginGetData(AsyncCallback cb, object st)
  		{
  			gd = new Func<object> (GetData);
  			return gd.BeginInvoke (cb, st);
  		}
  
  		public object EndGetData (IAsyncResult result)
  		{
  			return gd.EndInvoke (result);
  		}
  
  		public ObservableCollection<object> GetCollectionData()
  		{
  			return new ObservableCollection<object> { new DataType1 { Id = "B" }, new DataType1 { Id = "C" } };
  		}
  
  		Func<ObservableCollection<object>> gcd;
  		public IAsyncResult BeginGetCollectionData(AsyncCallback cb, object st)
  		{
  			gcd = new Func<ObservableCollection<object>> (GetCollectionData);
  			return gcd.BeginInvoke (cb, st);
  		}
  
  		public ObservableCollection<object> EndGetCollectionData (IAsyncResult result)
  		{
  			return gcd.EndInvoke (result);
  		}
  
  		public DataType2 GetNestedData()
  		{
  			return new DataType2 { Items = new ObservableCollection<object> { new DataType1 { Id = "D" }, new DataType1 { Id = "E" } } };
  		}
  
  		Func<DataType2> gnd;
  		public IAsyncResult BeginGetNestedData(AsyncCallback cb, object st)
  		{
  			gnd = new Func<DataType2> (GetNestedData);
  			return gnd.BeginInvoke (cb, st);
  		}
  
  		public DataType2 EndGetNestedData (IAsyncResult result)
  		{
  			return gnd.EndInvoke (result);
  		}
  
  		public JSMGetDatabasesResponse JSMGetDatabases(JSMGetDatabasesRequest request)
  		{
  			return new JSMGetDatabasesResponse { JSMGetDatabasesResult = "databases" };
  		}
  
  		Func<JSMGetDatabasesRequest, JSMGetDatabasesResponse> gjgdb;
  		public IAsyncResult BeginJSMGetDatabases(JSMGetDatabasesRequest request, AsyncCallback callback, object asyncState)
  		{
  			gjgdb = JSMGetDatabases;
  			return gjgdb.BeginInvoke (request, callback, asyncState);
  		}
  
  		public JSMGetDatabasesResponse EndJSMGetDatabases(IAsyncResult result)
  		{
  			return gjgdb.EndInvoke (result);
  		}
  	}
  }
  
  
  //------------------------------------------------------------------------------
  // <auto-generated>
  //     This code was generated by a tool.
  //     Runtime Version:4.0.30319.372
  //
  //     Changes to this file may cause incorrect behavior and will be lost if
  //     the code is regenerated.
  // </auto-generated>
  //------------------------------------------------------------------------------
  
  // 
  // This code was auto-generated by Microsoft.Silverlight.ServiceReference, version 4.0.50826.0
  // 
  namespace WebServiceMoonlightTest.ServiceReference2 {
      using System.Runtime.Serialization;
      
      
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
      [System.Runtime.Serialization.DataContractAttribute(Name="DataType1", Namespace="http://mynamespace")]
      public partial class DataType1 : object, System.ComponentModel.INotifyPropertyChanged {
          
          private string IdField;
          
          [System.Runtime.Serialization.DataMemberAttribute()]
          public string Id {
              get {
                  return this.IdField;
              }
              set {
                  if ((object.ReferenceEquals(this.IdField, value) != true)) {
                      this.IdField = value;
                      this.RaisePropertyChanged("Id");
                  }
              }
          }
          
          public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
          
          protected void RaisePropertyChanged(string propertyName) {
              System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
              if ((propertyChanged != null)) {
                  propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
              }
          }
      }
      
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
      [System.Runtime.Serialization.DataContractAttribute(Name="DataType2", Namespace="http://mynamespace")]
      [System.Runtime.Serialization.KnownTypeAttribute(typeof(WebServiceMoonlightTest.ServiceReference2.DataType1))]
      [System.Runtime.Serialization.KnownTypeAttribute(typeof(System.Collections.ObjectModel.ObservableCollection<object>))]
      public partial class DataType2 : object, System.ComponentModel.INotifyPropertyChanged {
          
          private System.Collections.ObjectModel.ObservableCollection<object> ItemsField;
          
          [System.Runtime.Serialization.DataMemberAttribute()]
          public System.Collections.ObjectModel.ObservableCollection<object> Items {
              get {
                  return this.ItemsField;
              }
              set {
                  if ((object.ReferenceEquals(this.ItemsField, value) != true)) {
                      this.ItemsField = value;
                      this.RaisePropertyChanged("Items");
                  }
              }
          }
          
          public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
          
          protected void RaisePropertyChanged(string propertyName) {
              System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
              if ((propertyChanged != null)) {
                  propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
              }
          }
      }
      
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      [System.ServiceModel.ServiceContractAttribute(Namespace="http://mynamespace", ConfigurationName="ServiceReference1.IService1")]
      public interface IService1 {
          
          [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://mynamespace/IService1/GetData", ReplyAction="http://mynamespace/IService1/GetDataResponse")]
          [System.ServiceModel.ServiceKnownTypeAttribute(typeof(WebServiceMoonlightTest.ServiceReference2.DataType1))]
          [System.ServiceModel.ServiceKnownTypeAttribute(typeof(WebServiceMoonlightTest.ServiceReference2.DataType2))]
          [System.ServiceModel.ServiceKnownTypeAttribute(typeof(System.Collections.ObjectModel.ObservableCollection<object>))]
          System.IAsyncResult BeginGetData(System.AsyncCallback callback, object asyncState);
          
  
gt:         object EndGetData(System.IAsyncResult result);