PageRenderTime 4ms CodeModel.GetById 2ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 1ms

/src/NServiceBus.Core.Tests/Serializers/XML/SerializerTests.cs

http://github.com/NServiceBus/NServiceBus
C# | 1538 lines | 1271 code | 266 blank | 1 comment | 15 complexity | f85e560df17849dce4384cfc187c0316 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1#pragma warning disable DE0006
   2namespace NServiceBus.Serializers.XML.Test
   3{
   4    using System;
   5    using System.Collections;
   6    using System.Collections.Generic;
   7    using System.Diagnostics;
   8    using System.Globalization;
   9    using System.IO;
  10    using System.Linq;
  11    using System.Net.Mail;
  12    using System.Runtime.Serialization;
  13    using System.Text;
  14    using System.Threading;
  15    using System.Xml;
  16    using System.Xml.Linq;
  17    using A;
  18    using AlternateNamespace;
  19    using B;
  20    using MessageInterfaces;
  21    using MessageInterfaces.MessageMapper.Reflection;
  22    using NUnit.Framework;
  23    using Serialization;
  24
  25    [TestFixture]
  26    public class SerializerTests
  27    {
  28        [Test]
  29        public void SerializeInvalidCharacters()
  30        {
  31            IMessageMapper mapper = new MessageMapper();
  32            var serializer = SerializerFactory.Create<MessageWithInvalidCharacter>();
  33            var msg = mapper.CreateInstance<MessageWithInvalidCharacter>();
  34
  35            var sb = new StringBuilder();
  36            sb.Append("Hello");
  37            sb.Append((char)0x1C);
  38            sb.Append("John");
  39            msg.Special = sb.ToString();
  40
  41            using (var stream = new MemoryStream())
  42            {
  43                serializer.Serialize(msg, stream);
  44                stream.Position = 0;
  45
  46                var msgArray = serializer.Deserialize(stream);
  47                var m = (MessageWithInvalidCharacter)msgArray[0];
  48                Assert.AreEqual(sb.ToString(), m.Special);
  49            }
  50        }
  51
  52        [Test] //note: This is not a desired behavior, but this test documents this limitation
  53        public void Limitation_Does_not_handle_types_implementing_ISerializable()
  54        {
  55            var message = new MessageImplementingISerializable("test");
  56
  57            var serializer = SerializerFactory.Create<MessageImplementingISerializable>();
  58
  59            using (var stream = new MemoryStream())
  60            {
  61                serializer.Serialize(message, stream);
  62                stream.Position = 0;
  63
  64                var result = (MessageImplementingISerializable)serializer.Deserialize(stream)[0];
  65
  66                Assert.Null(result.ReadOnlyProperty);
  67            }
  68        }
  69
  70        [Test]
  71        public void Should_handle_struct_message()
  72        {
  73            var message = new StructMessage
  74            {
  75                SomeProperty = "property",
  76                SomeField = "field"
  77            };
  78
  79            var serializer = SerializerFactory.Create<StructMessage>();
  80
  81            using (var stream = new MemoryStream())
  82            {
  83                serializer.Serialize(message, stream);
  84                stream.Position = 0;
  85
  86                var result = (StructMessage)serializer.Deserialize(stream)[0];
  87
  88                Assert.AreEqual(message.SomeField, result.SomeField);
  89                Assert.AreEqual(message.SomeProperty, result.SomeProperty);
  90            }
  91        }
  92
  93        [Test] //note: This is not a desired behavior, but this test documents this limitation
  94        public void Limitation_Does_not_handle_message_with_struct_property()
  95        {
  96            var message = new MessageWithStructProperty();
  97
  98            var serializer = SerializerFactory.Create<MessageWithStructProperty>();
  99
 100            using (var stream = new MemoryStream())
 101            {
 102                serializer.Serialize(message, stream);
 103                stream.Position = 0;
 104
 105                var ex = Assert.Throws<Exception>(() => serializer.Deserialize(stream));
 106
 107                StringAssert.StartsWith("Type not supported by the serializer", ex.Message);
 108            }
 109        }
 110
 111        [Test] //note: This is not a desired behavior, but this test documents this limitation
 112        public void Limitation_Does_not_handle_concrete_message_with_invalid_interface_property()
 113        {
 114            var message = new MessageWithInvalidInterfaceProperty
 115            {
 116                InterfaceProperty = new InvalidInterfacePropertyImplementation
 117                {
 118                    SomeProperty = "test"
 119                }
 120            };
 121            var serializer = SerializerFactory.Create<MessageWithInvalidInterfaceProperty>();
 122
 123            using (var stream = new MemoryStream())
 124            {
 125                serializer.Serialize(message, stream);
 126                stream.Position = 0;
 127
 128                Assert.Throws<Exception>(() => serializer.Deserialize(stream));
 129            }
 130        }
 131
 132        [Test]
 133        public void Should_handle_concrete_message_with_interface_property()
 134        {
 135            var message = new MessageWithInterfaceProperty
 136            {
 137                InterfaceProperty = new InterfacePropertyImplementation
 138                {
 139                    SomeProperty = "test"
 140                }
 141            };
 142            var serializer = SerializerFactory.Create<MessageWithInterfaceProperty>();
 143
 144            using (var stream = new MemoryStream())
 145            {
 146                serializer.Serialize(message, stream);
 147
 148                stream.Position = 0;
 149
 150                var result = (MessageWithInterfaceProperty)serializer.Deserialize(stream)[0];
 151
 152                Assert.AreEqual(message.InterfaceProperty.SomeProperty, result.InterfaceProperty.SomeProperty);
 153            }
 154        }
 155
 156        [Test]
 157        public void Should_handle_interface_message_with_interface_property()
 158        {
 159            IMessageWithInterfaceProperty message = new InterfaceMessageWithInterfacePropertyImplementation
 160            {
 161                InterfaceProperty = new InterfacePropertyImplementation
 162                {
 163                    SomeProperty = "test"
 164                }
 165            };
 166            var serializer = SerializerFactory.Create<IMessageWithInterfaceProperty>();
 167
 168            using (var stream = new MemoryStream())
 169            {
 170                serializer.Serialize(message, stream);
 171
 172                stream.Position = 0;
 173
 174                var result = (IMessageWithInterfaceProperty)serializer.Deserialize(stream, new[]
 175                {
 176                    typeof(IMessageWithInterfaceProperty)
 177                })[0];
 178
 179                Assert.AreEqual(message.InterfaceProperty.SomeProperty, result.InterfaceProperty.SomeProperty);
 180            }
 181        }
 182
 183        [Test, Ignore("ArrayList is not supported")]
 184        public void Should_deserialize_arrayList()
 185        {
 186            var expected = new ArrayList
 187            {
 188                "Value1",
 189                "Value2",
 190                "Value3"
 191            };
 192            var result = ExecuteSerializer.ForMessage<MessageWithArrayList>(m3 => m3.ArrayList = expected);
 193
 194            CollectionAssert.AreEqual(expected, result.ArrayList);
 195        }
 196
 197        [Test, Ignore("Hashtable is not supported")]
 198        public void Should_deserialize_hashtable()
 199        {
 200            var expected = new Hashtable
 201            {
 202                {"Key1", "Value1"},
 203                {"Key2", "Value2"},
 204                {"Key3", "Value3"}
 205            };
 206            var result = ExecuteSerializer.ForMessage<MessageWithHashtable>(m3 => m3.Hashtable = expected);
 207
 208            CollectionAssert.AreEqual(expected, result.Hashtable);
 209        }
 210
 211        [Test]
 212        public void Should_deserialize_multiple_messages_from_different_namespaces()
 213        {
 214            var xml = @"<?xml version=""1.0"" ?>
 215<Messages
 216    xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
 217    xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
 218    xmlns=""http://tempuri.net/NServiceBus.Serializers.XML.Test.A""
 219    xmlns:q1=""http://tempuri.net/NServiceBus.Serializers.XML.Test.B"">
 220    <Command1>
 221        <Id>1eb17e5d-8573-49af-a5cb-76b4a602bb79</Id>
 222    </Command1>
 223    <q1:Command2>
 224        <Id>ad3b5a84-6cf1-4376-aa2d-058b1120c12f</Id>
 225    </q1:Command2>
 226</Messages>
 227";
 228            using (var stream = new MemoryStream())
 229            {
 230                var writer = new StreamWriter(stream);
 231                writer.Write(xml);
 232                writer.Flush();
 233                stream.Position = 0;
 234                var msgArray = SerializerFactory.Create(typeof(Command1), typeof(Command2)).Deserialize(stream);
 235
 236                Assert.AreEqual(typeof(Command1), msgArray[0].GetType());
 237                Assert.AreEqual(typeof(Command2), msgArray[1].GetType());
 238            }
 239        }
 240
 241        [Test]
 242        public void Should_infer_message_type_from_root_node_if_type_is_known()
 243        {
 244            using (var stream = new MemoryStream())
 245            {
 246                var writer = new StreamWriter(stream);
 247                writer.WriteLine("<NServiceBus.Serializers.XML.Test.MessageWithDouble><Double>23.4</Double></NServiceBus.Serializers.XML.Test.MessageWithDouble>");
 248                writer.Flush();
 249                stream.Position = 0;
 250
 251                var msgArray = SerializerFactory.Create(typeof(MessageWithDouble)).Deserialize(stream);
 252
 253                Assert.AreEqual(typeof(MessageWithDouble), msgArray[0].GetType());
 254            }
 255        }
 256
 257        [Test]
 258        public void Deserialize_private_message_with_two_unrelated_interface_without_wrapping()
 259        {
 260            var serializer = SerializerFactory.Create(typeof(CompositeMessage), typeof(IMyEventA), typeof(IMyEventB));
 261            var deserializer = SerializerFactory.Create(typeof(IMyEventA), typeof(IMyEventB));
 262
 263            using (var stream = new MemoryStream())
 264            {
 265                var msg = new CompositeMessage
 266                {
 267                    IntValue = 42,
 268                    StringValue = "Answer"
 269                };
 270
 271                serializer.Serialize(msg, stream);
 272
 273                stream.Position = 0;
 274
 275                var result = deserializer.Deserialize(stream, new[]
 276                {
 277                    typeof(IMyEventA),
 278                    typeof(IMyEventB)
 279                });
 280                var a = (IMyEventA)result[0];
 281                var b = (IMyEventB)result[1];
 282                Assert.AreEqual(42, b.IntValue);
 283                Assert.AreEqual("Answer", a.StringValue);
 284            }
 285        }
 286
 287        [Test]
 288        public void Should_be_able_to_serialize_single_message_without_wrapping_element()
 289        {
 290            Serializer.ForMessage<EmptyMessage>(new EmptyMessage())
 291                .AssertResultingXml(d => d.DocumentElement.Name == "EmptyMessage", "Root should be message typename");
 292        }
 293
 294        [Test]
 295        public void Should_be_able_to_serialize_single_message_without_wrapping_xml_raw_data()
 296        {
 297            const string XmlElement = "<SomeClass xmlns=\"http://nservicebus.com\"><SomeProperty value=\"Bar\" /></SomeClass>";
 298            const string XmlDocument = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + XmlElement;
 299
 300            var messageWithXDocument = new MessageWithXDocument
 301            {
 302                Document = XDocument.Load(new StringReader(XmlDocument))
 303            };
 304            var messageWithXElement = new MessageWithXElement
 305            {
 306                Document = XElement.Load(new StringReader(XmlElement))
 307            };
 308
 309            Serializer.ForMessage<MessageWithXDocument>(messageWithXDocument, s => { s.SkipWrappingRawXml = true; })
 310                .AssertResultingXml(d => d.DocumentElement.ChildNodes[0].FirstChild.Name != "Document", "Property name should not be available");
 311
 312            Serializer.ForMessage<MessageWithXElement>(messageWithXElement, s => { s.SkipWrappingRawXml = true; })
 313                .AssertResultingXml(d => d.DocumentElement.ChildNodes[0].FirstChild.Name != "Document", "Property name should not be available");
 314        }
 315
 316        [Test]
 317        public void Should_deserialize_messages_where_xml_raw_data_root_element_matches_property_name()
 318        {
 319            const string XmlElement = "<Document xmlns=\"http://nservicebus.com\"><SomeProperty value=\"Bar\" /></Document>";
 320            const string XmlDocument = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + XmlElement;
 321
 322            var messageWithXDocument = new MessageWithXDocument
 323            {
 324                Document = XDocument.Load(new StringReader(XmlDocument))
 325            };
 326            var messageWithXElement = new MessageWithXElement
 327            {
 328                Document = XElement.Load(new StringReader(XmlElement))
 329            };
 330
 331            var serializer = SerializerFactory.Create<MessageWithXDocument>();
 332            serializer.SkipWrappingRawXml = true;
 333
 334            using (var stream = new MemoryStream())
 335            {
 336                serializer.Serialize(messageWithXDocument, stream);
 337                stream.Position = 0;
 338
 339                serializer = SerializerFactory.Create(typeof(MessageWithXDocument));
 340                serializer.SkipWrappingRawXml = true;
 341
 342                var msg = serializer.Deserialize(stream).Cast<MessageWithXDocument>().Single();
 343
 344                Assert.NotNull(msg.Document);
 345                Assert.AreEqual("Document", msg.Document.Root.Name.LocalName);
 346            }
 347
 348            serializer = SerializerFactory.Create<MessageWithXElement>();
 349            serializer.SkipWrappingRawXml = true;
 350
 351            using (var stream = new MemoryStream())
 352            {
 353                serializer.Serialize(messageWithXElement, stream);
 354                stream.Position = 0;
 355
 356                serializer = SerializerFactory.Create(typeof(MessageWithXElement));
 357                serializer.SkipWrappingRawXml = true;
 358
 359                var msg = serializer.Deserialize(stream).Cast<MessageWithXElement>().Single();
 360
 361                Assert.NotNull(msg.Document);
 362                Assert.AreEqual("Document", msg.Document.Name.LocalName);
 363            }
 364        }
 365
 366        [Test]
 367        public void Should_be_able_to_serialize_single_message_with_default_namespaces_and_then_deserialize()
 368        {
 369            var serializer = SerializerFactory.Create<MessageWithDouble>();
 370            var msg = new MessageWithDouble();
 371
 372            using (var stream = new MemoryStream())
 373            {
 374                serializer.Serialize(msg, stream);
 375                stream.Position = 0;
 376
 377                var msgArray = SerializerFactory.Create(typeof(MessageWithDouble)).Deserialize(stream);
 378
 379                Assert.AreEqual(typeof(MessageWithDouble), msgArray[0].GetType());
 380            }
 381        }
 382
 383        [Test]
 384        public void Should_be_able_to_serialize_single_message_with_default_namespaces()
 385        {
 386            var serializer = SerializerFactory.Create<EmptyMessage>();
 387            var msg = new EmptyMessage();
 388
 389            var expected = @"<EmptyMessage xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://tempuri.net/NServiceBus.Serializers.XML.Test""></EmptyMessage>";
 390
 391            AssertSerializedEquals(serializer, msg, expected);
 392        }
 393
 394        [Test]
 395        public void Should_be_able_to_serialize_single_message_with_specified_namespaces()
 396        {
 397            var serializer = SerializerFactory.Create<EmptyMessage>();
 398            serializer.Namespace = "http://super.com";
 399            var msg = new EmptyMessage();
 400
 401            var expected = @"<EmptyMessage xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://super.com/NServiceBus.Serializers.XML.Test""></EmptyMessage>";
 402
 403            AssertSerializedEquals(serializer, msg, expected);
 404        }
 405
 406        [Test]
 407        public void Should_be_able_to_serialize_single_message_with_specified_namespace_with_trailing_forward_slashes()
 408        {
 409            var serializer = SerializerFactory.Create<EmptyMessage>();
 410            serializer.Namespace = "http://super.com///";
 411            var msg = new EmptyMessage();
 412
 413            var expected = @"<EmptyMessage xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://super.com/NServiceBus.Serializers.XML.Test""></EmptyMessage>";
 414
 415            AssertSerializedEquals(serializer, msg, expected);
 416        }
 417
 418        static void AssertSerializedEquals(IMessageSerializer serializer, IMessage msg, string expected)
 419        {
 420            using (var stream = new MemoryStream())
 421            {
 422                serializer.Serialize(msg, stream);
 423                stream.Position = 0;
 424
 425                string result;
 426                using (var reader = new StreamReader(stream))
 427                {
 428                    result = XDocument.Load(reader).ToString();
 429                }
 430
 431                Assert.AreEqual(expected, result);
 432            }
 433        }
 434
 435        [Test]
 436        public void Should_deserialize_a_single_message_with_typeName_passed_in_externally()
 437        {
 438            using (var stream = new MemoryStream())
 439            {
 440                var writer = new StreamWriter(stream);
 441                writer.WriteLine("<WhatEver><Double>23.4</Double></WhatEver>");
 442                writer.Flush();
 443                stream.Position = 0;
 444
 445                var msgArray = SerializerFactory.Create(typeof(MessageWithDouble)).Deserialize(stream, new[]
 446                {
 447                    typeof(MessageWithDouble)
 448                });
 449
 450                Assert.AreEqual(typeof(MessageWithDouble), msgArray[0].GetType());
 451            }
 452        }
 453
 454        [Test]
 455        public void Should_deserialize_a_single_message_with_typeName_passed_in_externally_even_when_not_initialized_with_type()
 456        {
 457            using (var stream = new MemoryStream())
 458            {
 459                var writer = new StreamWriter(stream);
 460                writer.WriteLine("<WhatEver><Double>23.4</Double></WhatEver>");
 461                writer.Flush();
 462                stream.Position = 0;
 463
 464                var msgArray = SerializerFactory.Create()
 465                    .Deserialize(stream, new[]
 466                    {
 467                        typeof(MessageWithDouble)
 468                    });
 469
 470                Assert.AreEqual(23.4, ((MessageWithDouble)msgArray[0]).Double);
 471            }
 472        }
 473
 474        [Test]
 475        public void Should_deserialize_a_batched_messages_with_typeName_passed_in_externally()
 476        {
 477            using (var stream = new MemoryStream())
 478            {
 479                var writer = new StreamWriter(stream);
 480                writer.WriteLine("<Messages><WhatEver><Double>23.4</Double></WhatEver><TheEmptyMessage></TheEmptyMessage></Messages>");
 481                writer.Flush();
 482                stream.Position = 0;
 483
 484                var msgArray = SerializerFactory.Create(typeof(MessageWithDouble), typeof(EmptyMessage))
 485                    .Deserialize(stream, new[]
 486                    {
 487                        typeof(MessageWithDouble),
 488                        typeof(EmptyMessage)
 489                    });
 490
 491                Assert.AreEqual(23.4, ((MessageWithDouble)msgArray[0]).Double);
 492                Assert.AreEqual(typeof(EmptyMessage), msgArray[1].GetType());
 493            }
 494        }
 495
 496        [Test]
 497        public void Should_deserialize_a_batched_messages_with_typeName_passed_in_externally_even_when_not_initialized_with_type()
 498        {
 499            using (var stream = new MemoryStream())
 500            {
 501                var writer = new StreamWriter(stream);
 502                writer.WriteLine("<Messages><WhatEver><Double>23.4</Double></WhatEver><TheEmptyMessage></TheEmptyMessage></Messages>");
 503                writer.Flush();
 504                stream.Position = 0;
 505
 506                var msgArray = SerializerFactory.Create()
 507                    .Deserialize(stream, new[]
 508                    {
 509                        typeof(MessageWithDouble),
 510                        typeof(EmptyMessage)
 511                    });
 512
 513                Assert.AreEqual(23.4, ((MessageWithDouble)msgArray[0]).Double);
 514                Assert.AreEqual(typeof(EmptyMessage), msgArray[1].GetType());
 515            }
 516        }
 517
 518        [Test]
 519        public void TestMultipleInterfacesDuplicatedProperty()
 520        {
 521            var mapper = new MessageMapper();
 522            var serializer = SerializerFactory.Create<IThird>(mapper);
 523            var msgBeforeSerialization = mapper.CreateInstance<IThird>(x => x.FirstName = "Danny");
 524
 525            var count = 0;
 526            using (var stream = new MemoryStream())
 527            {
 528                serializer.Serialize(msgBeforeSerialization, stream);
 529                stream.Position = 0;
 530
 531                var reader = XmlReader.Create(stream);
 532
 533                while (reader.Read())
 534                    if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "FirstName"))
 535                        count++;
 536            }
 537            Assert.AreEqual(count, 1);
 538        }
 539
 540
 541        [Test]
 542        public void Generic_properties_should_be_supported()
 543        {
 544            var result = ExecuteSerializer.ForMessage<MessageWithGenericProperty>(m =>
 545            {
 546                m.GenericProperty =
 547                    new GenericProperty<string>("test")
 548                    {
 549                        WhatEver = "a property"
 550                    };
 551            });
 552
 553            Assert.AreEqual("a property", result.GenericProperty.WhatEver);
 554        }
 555
 556
 557        [Test]
 558        public void Culture()
 559        {
 560            var serializer = SerializerFactory.Create<MessageWithDouble>();
 561            var val = 65.36;
 562            var msg = new MessageWithDouble
 563            {
 564                Double = val
 565            };
 566
 567            Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
 568
 569            var stream = new MemoryStream();
 570            serializer.Serialize(msg, stream);
 571
 572            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
 573
 574            stream.Position = 0;
 575            var msgArray = serializer.Deserialize(stream);
 576            var m = (MessageWithDouble)msgArray[0];
 577
 578            Assert.AreEqual(val, m.Double);
 579
 580            stream.Dispose();
 581        }
 582
 583        [Test]
 584        public void Comparison()
 585        {
 586            TestInterfaces();
 587            TestDataContractSerializer();
 588        }
 589
 590        [Test]
 591        public void TestInterfaces()
 592        {
 593            var mapper = new MessageMapper();
 594            var serializer = SerializerFactory.Create<ISecondSerializableMessage>(mapper);
 595
 596
 597            var o = mapper.CreateInstance<ISecondSerializableMessage>();
 598
 599            o.Id = Guid.NewGuid();
 600            o.Age = 10;
 601            o.Address = Guid.NewGuid().ToString();
 602            o.Int = 7;
 603            o.Name = "udi";
 604            o.Uri = new Uri("http://www.UdiDahan.com/");
 605            o.Risk = new Risk
 606            {
 607                Percent = 0.15D,
 608                Annum = true,
 609                Accuracy = 0.314M
 610            };
 611            o.Some = SomeEnum.B;
 612            o.Start = DateTime.Now;
 613            o.Duration = TimeSpan.Parse("-01:15:27.123");
 614            o.Offset = DateTimeOffset.Now;
 615            o.Lookup = new MyDictionary();
 616            o.Lookup["1"] = "1";
 617            o.Foos = new Dictionary<string, List<Foo>>();
 618            o.Foos["foo1"] = new List<Foo>(new[]
 619            {
 620                new Foo
 621                {
 622                    Name = "1",
 623                    Title = "1"
 624                },
 625                new Foo
 626                {
 627                    Name = "2",
 628                    Title = "2"
 629                }
 630            });
 631            o.Data = new byte[]
 632            {
 633                1,
 634                2,
 635                3,
 636                4,
 637                5,
 638                4,
 639                3,
 640                2,
 641                1
 642            };
 643            o.SomeStrings = new List<string>
 644            {
 645                "a",
 646                "b",
 647                "c"
 648            };
 649
 650            o.ArrayFoos = new[]
 651            {
 652                new Foo
 653                {
 654                    Name = "FooArray1",
 655                    Title = "Mr."
 656                },
 657                new Foo
 658                {
 659                    Name = "FooAray2",
 660                    Title = "Mrs"
 661                }
 662            };
 663            o.Bars = new[]
 664            {
 665                new Bar
 666                {
 667                    Name = "Bar1",
 668                    Length = 1
 669                },
 670                new Bar
 671                {
 672                    Name = "BAr2",
 673                    Length = 5
 674                }
 675            };
 676            o.NaturalNumbers = new HashSet<int>(new[]
 677            {
 678                0,
 679                1,
 680                2,
 681                3,
 682                4,
 683                5,
 684                6,
 685                7,
 686                8,
 687                9
 688            });
 689            o.Developers = new HashSet<string>(new[]
 690            {
 691                "Udi Dahan",
 692                "Andreas Ohlund",
 693                "Matt Burton",
 694                "Jonathan Oliver et al"
 695            });
 696
 697            o.Parent = mapper.CreateInstance<IFirstSerializableMessage>();
 698            o.Parent.Name = "udi";
 699            o.Parent.Age = 10;
 700            o.Parent.Address = Guid.NewGuid().ToString();
 701            o.Parent.Int = 7;
 702            o.Parent.Name = "-1";
 703            o.Parent.Risk = new Risk
 704            {
 705                Percent = 0.15D,
 706                Annum = true,
 707                Accuracy = 0.314M
 708            };
 709
 710            o.Names = new List<IFirstSerializableMessage>();
 711            for (var i = 0; i < number; i++)
 712            {
 713                var firstMessage = mapper.CreateInstance<IFirstSerializableMessage>();
 714                o.Names.Add(firstMessage);
 715                firstMessage.Age = 10;
 716                firstMessage.Address = Guid.NewGuid().ToString();
 717                firstMessage.Int = 7;
 718                firstMessage.Name = i.ToString();
 719                firstMessage.Risk = new Risk
 720                {
 721                    Percent = 0.15D,
 722                    Annum = true,
 723                    Accuracy = 0.314M
 724                };
 725            }
 726
 727            o.MoreNames = o.Names.ToArray();
 728
 729            Time(o, serializer);
 730        }
 731
 732        [Test]
 733        public void TestDataContractSerializer()
 734        {
 735            var o = CreateSecondSerializableMessage();
 736            var messages = new IMessage[]
 737            {
 738                o
 739            };
 740
 741            var dataContractSerializer = new DataContractSerializer(typeof(ArrayList), new[]
 742            {
 743                typeof(SecondSerializableMessage),
 744                typeof(SomeEnum),
 745                typeof(FirstSerializableMessage),
 746                typeof(Risk),
 747                typeof(List<FirstSerializableMessage>)
 748            });
 749
 750            var sw = new Stopwatch();
 751            sw.Start();
 752
 753            var xmlWriterSettings = new XmlWriterSettings
 754            {
 755                OmitXmlDeclaration = false
 756            };
 757
 758            var xmlReaderSettings = new XmlReaderSettings
 759            {
 760                IgnoreProcessingInstructions = true,
 761                ValidationType = ValidationType.None,
 762                IgnoreWhitespace = true,
 763                CheckCharacters = false,
 764                ConformanceLevel = ConformanceLevel.Auto
 765            };
 766
 767            for (var i = 0; i < numberOfIterations; i++)
 768                using (var stream = new MemoryStream())
 769                    DataContractSerialize(xmlWriterSettings, dataContractSerializer, messages, stream);
 770
 771            sw.Stop();
 772            Debug.WriteLine("serialization " + sw.Elapsed);
 773
 774            sw.Reset();
 775
 776            File.Delete("a.xml");
 777            using (var fs = File.Open("a.xml", FileMode.OpenOrCreate))
 778                DataContractSerialize(xmlWriterSettings, dataContractSerializer, messages, fs);
 779
 780            var s = new MemoryStream();
 781            DataContractSerialize(xmlWriterSettings, dataContractSerializer, messages, s);
 782            var buffer = s.GetBuffer();
 783            s.Dispose();
 784
 785            sw.Start();
 786
 787            for (var i = 0; i < numberOfIterations; i++)
 788                using (var reader = XmlReader.Create(new MemoryStream(buffer), xmlReaderSettings))
 789                    dataContractSerializer.ReadObject(reader);
 790
 791            sw.Stop();
 792            Debug.WriteLine("deserializing: " + sw.Elapsed);
 793        }
 794
 795        [Test]
 796        public void SerializeLists()
 797        {
 798            IMessageMapper mapper = new MessageMapper();
 799            var serializer = SerializerFactory.Create<MessageWithList>();
 800            var msg = mapper.CreateInstance<MessageWithList>();
 801
 802            msg.Items = new List<MessageWithListItem>
 803            {
 804                new MessageWithListItem
 805                {
 806                    Data = "Hello"
 807                }
 808            };
 809
 810            using (var stream = new MemoryStream())
 811            {
 812                serializer.Serialize(msg, stream);
 813                stream.Position = 0;
 814
 815                var msgArray = serializer.Deserialize(stream);
 816                var m = (MessageWithList)msgArray[0];
 817                Assert.AreEqual("Hello", m.Items.First().Data);
 818            }
 819        }
 820
 821        [Test]
 822        public void SerializeClosedGenericListsInAlternateNamespace()
 823        {
 824            IMessageMapper mapper = new MessageMapper();
 825            var serializer = SerializerFactory.Create<MessageWithClosedListInAlternateNamespace>();
 826            var msg = mapper.CreateInstance<MessageWithClosedListInAlternateNamespace>();
 827
 828            msg.Items = new AlternateItemList
 829            {
 830                new MessageWithListItemAlternate
 831                {
 832                    Data = "Hello"
 833                }
 834            };
 835
 836            using (var stream = new MemoryStream())
 837            {
 838                serializer.Serialize(msg, stream);
 839                stream.Position = 0;
 840
 841                var msgArray = serializer.Deserialize(stream);
 842                var m = (MessageWithClosedListInAlternateNamespace)msgArray[0];
 843                Assert.AreEqual("Hello", m.Items.First().Data);
 844            }
 845        }
 846
 847        [Test]
 848        public void SerializeClosedGenericListsInAlternateNamespaceMultipleIEnumerableImplementations()
 849        {
 850            IMessageMapper mapper = new MessageMapper();
 851            var serializer = SerializerFactory.Create<MessageWithClosedListInAlternateNamespaceMultipleIEnumerableImplementations>();
 852            var msg = mapper.CreateInstance<MessageWithClosedListInAlternateNamespaceMultipleIEnumerableImplementations>();
 853
 854            msg.Items = new AlternateItemListMultipleIEnumerableImplementations
 855            {
 856                new MessageWithListItemAlternate
 857                {
 858                    Data = "Hello"
 859                }
 860            };
 861
 862            using (var stream = new MemoryStream())
 863            {
 864                serializer.Serialize(msg, stream);
 865                stream.Position = 0;
 866
 867                var msgArray = serializer.Deserialize(stream);
 868                var m = (MessageWithClosedListInAlternateNamespaceMultipleIEnumerableImplementations)msgArray[0];
 869                Assert.AreEqual("Hello", m.Items.First<MessageWithListItemAlternate>().Data);
 870            }
 871        }
 872
 873        [Test]
 874        public void SerializeClosedGenericListsInAlternateNamespaceMultipleIListImplementations()
 875        {
 876            IMessageMapper mapper = new MessageMapper();
 877            var serializer = SerializerFactory.Create<MessageWithClosedListInAlternateNamespaceMultipleIListImplementations>();
 878            var msg = mapper.CreateInstance<MessageWithClosedListInAlternateNamespaceMultipleIListImplementations>();
 879
 880            msg.Items = new AlternateItemListMultipleIListImplementations
 881            {
 882                new MessageWithListItemAlternate
 883                {
 884                    Data = "Hello"
 885                }
 886            };
 887
 888            using (var stream = new MemoryStream())
 889            {
 890                serializer.Serialize(msg, stream);
 891                stream.Position = 0;
 892
 893                var msgArray = serializer.Deserialize(stream);
 894                var m = (MessageWithClosedListInAlternateNamespaceMultipleIListImplementations)msgArray[0];
 895                Assert.AreEqual("Hello", m.Items.First<MessageWithListItemAlternate>().Data);
 896            }
 897        }
 898
 899        [Test]
 900        public void SerializeClosedGenericListsInSameNamespace()
 901        {
 902            IMessageMapper mapper = new MessageMapper();
 903            var serializer = SerializerFactory.Create<MessageWithClosedList>();
 904            var msg = mapper.CreateInstance<MessageWithClosedList>();
 905
 906            msg.Items = new ItemList
 907            {
 908                new MessageWithListItem
 909                {
 910                    Data = "Hello"
 911                }
 912            };
 913
 914            using (var stream = new MemoryStream())
 915            {
 916                serializer.Serialize(msg, stream);
 917                stream.Position = 0;
 918
 919                var msgArray = serializer.Deserialize(stream);
 920                var m = (MessageWithClosedList)msgArray[0];
 921                Assert.AreEqual("Hello", m.Items.First().Data);
 922            }
 923        }
 924
 925        [Test]
 926        public void SerializeEmptyLists()
 927        {
 928            IMessageMapper mapper = new MessageMapper();
 929            var serializer = SerializerFactory.Create<MessageWithList>();
 930            var msg = mapper.CreateInstance<MessageWithList>();
 931
 932            msg.Items = new List<MessageWithListItem>();
 933
 934            using (var stream = new MemoryStream())
 935            {
 936                serializer.Serialize(msg, stream);
 937                stream.Position = 0;
 938
 939                var msgArray = serializer.Deserialize(stream);
 940                var m = (MessageWithList)msgArray[0];
 941                Assert.IsEmpty(m.Items);
 942            }
 943        }
 944
 945
 946        void DataContractSerialize(XmlWriterSettings xmlWriterSettings, DataContractSerializer dataContractSerializer, IMessage[] messages, Stream stream)
 947        {
 948            var o = new ArrayList(messages);
 949            using (var xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
 950            {
 951                dataContractSerializer.WriteStartObject(xmlWriter, o);
 952                dataContractSerializer.WriteObjectContent(xmlWriter, o);
 953                dataContractSerializer.WriteEndObject(xmlWriter);
 954            }
 955        }
 956
 957        SecondSerializableMessage CreateSecondSerializableMessage()
 958        {
 959            var secondMessage = new SecondSerializableMessage
 960            {
 961                Id = Guid.NewGuid(),
 962                Age = 10,
 963                Address = Guid.NewGuid().ToString(),
 964                Int = 7,
 965                Name = "udi",
 966                Risk = new Risk
 967                {
 968                    Percent = 0.15D,
 969                    Annum = true,
 970                    Accuracy = 0.314M
 971                },
 972                Some = SomeEnum.B,
 973                Start = DateTime.Now,
 974                Duration = TimeSpan.Parse("-01:15:27.123"),
 975                Offset = DateTimeOffset.Now,
 976                Parent = new FirstSerializableMessage
 977                {
 978                    Age = 10,
 979                    Address = Guid.NewGuid().ToString(),
 980                    Int = 7,
 981                    Name = "-1",
 982                    Risk = new Risk
 983                    {
 984                        Percent = 0.15D,
 985                        Annum = true,
 986                        Accuracy = 0.314M
 987                    }
 988                },
 989                Names = new List<FirstSerializableMessage>()
 990            };
 991
 992            for (var i = 0; i < number; i++)
 993            {
 994                var firstMessage = new FirstSerializableMessage();
 995                secondMessage.Names.Add(firstMessage);
 996                firstMessage.Age = 10;
 997                firstMessage.Address = Guid.NewGuid().ToString();
 998                firstMessage.Int = 7;
 999                firstMessage.Name = i.ToString();
1000                firstMessage.Risk = new Risk
1001                {
1002                    Percent = 0.15D,
1003                    Annum = true,
1004                    Accuracy = 0.314M
1005                };
1006            }
1007
1008            secondMessage.MoreNames = secondMessage.Names.ToArray();
1009
1010            return secondMessage;
1011        }
1012
1013        void Time(object message, IMessageSerializer serializer)
1014        {
1015            var watch = new Stopwatch();
1016            watch.Start();
1017
1018            for (var i = 0; i < numberOfIterations; i++)
1019                using (var stream = new MemoryStream())
1020                    serializer.Serialize(message, stream);
1021
1022            watch.Stop();
1023            Debug.WriteLine("Serializing: " + watch.Elapsed);
1024
1025            watch.Reset();
1026
1027            byte[] buffer;
1028            using (var s = new MemoryStream())
1029            {
1030                serializer.Serialize(message, s);
1031                buffer = s.ToArray();
1032            }
1033
1034            watch.Start();
1035
1036            for (var i = 0; i < numberOfIterations; i++)
1037            {
1038                using (var forDeserializing = new MemoryStream(buffer))
1039                {
1040                    serializer.Deserialize(forDeserializing);
1041                }
1042            }
1043
1044            watch.Stop();
1045            Debug.WriteLine("Deserializing: " + watch.Elapsed);
1046        }
1047
1048
1049        [Test]
1050        public void NestedObjectWithNullPropertiesShouldBeSerialized()
1051        {
1052            var result = ExecuteSerializer.ForMessage<MessageWithNestedObject>(m => { m.NestedObject = new MessageWithNullProperty(); });
1053            Assert.IsNotNull(result.NestedObject);
1054        }
1055
1056        [Test]
1057        public void Messages_with_generic_properties_closing_nullables_should_be_supported()
1058        {
1059            var theTime = DateTime.Now;
1060
1061            var result = ExecuteSerializer.ForMessage<MessageWithGenericPropClosingNullable>(
1062                m =>
1063                {
1064                    m.GenericNullable = new GenericPropertyWithNullable<DateTime?>
1065                    {
1066                        TheType = theTime
1067                    };
1068                    m.Whatever = "fdsfsdfsd";
1069                });
1070            Assert.IsNotNull(result.GenericNullable.TheType == theTime);
1071        }
1072
1073        [Test]
1074        public void When_Using_A_Dictionary_With_An_object_As_Key_should_throw()
1075        {
1076            Assert.Throws<NotSupportedException>(() => SerializerFactory.Create<MessageWithDictionaryWithAnObjectAsKey>());
1077        }
1078
1079        [Test]
1080        public void When_Using_A_Dictionary_With_An_Object_As_Value_should_throw()
1081        {
1082            Assert.Throws<NotSupportedException>(() => SerializerFactory.Create<MessageWithDictionaryWithAnObjectAsValue>());
1083        }
1084
1085
1086        [Test, Ignore("We're not supporting this type")]
1087        public void System_classes_with_non_default_constructors_should_be_supported()
1088        {
1089            var message = new MailMessage("from@gmail.com", "to@hotmail.com")
1090            {
1091                Subject = "Testing the NSB email support",
1092                Body = "Hello"
1093            };
1094
1095            var result = ExecuteSerializer.ForMessage<MessageWithSystemClassAsProperty>(
1096                m => { m.MailMessage = message; });
1097            Assert.IsNotNull(result.MailMessage);
1098            Assert.AreEqual("from@gmail.com", result.MailMessage.From.Address);
1099            Assert.AreEqual(message.To.First(), result.MailMessage.To.First());
1100            Assert.AreEqual(message.BodyEncoding.CodePage, result.MailMessage.BodyEncoding.CodePage);
1101            Assert.AreEqual(message.BodyEncoding.EncoderFallback.MaxCharCount, result.MailMessage.BodyEncoding.EncoderFallback.MaxCharCount);
1102        }
1103
1104        [Test, Ignore("We're currently not supporting polymorphic properties")]
1105        public void Messages_with_polymorphic_properties_should_be_supported()
1106        {
1107            var message = new PolyMessage
1108            {
1109                BaseType = new ChildOfBase
1110                {
1111                    BaseTypeProp = "base",
1112                    ChildProp = "Child"
1113                }
1114            };
1115
1116            var result = ExecuteSerializer.ForMessage<PolyMessage>(message);
1117
1118            Assert.AreEqual(message.BaseType.BaseTypeProp, result.BaseType.BaseTypeProp);
1119
1120            Assert.AreEqual(((ChildOfBase)message.BaseType).ChildProp, ((ChildOfBase)result.BaseType).ChildProp);
1121        }
1122
1123        [Test]
1124        public void When_Using_Property_WithXContainerAssignable_should_preserve_xml()
1125        {
1126            const string XmlElement = "<SomeClass xmlns=\"http://nservicebus.com\"><SomeProperty value=\"Bar\" ></SomeProperty></SomeClass>";
1127            const string XmlDocument = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + XmlElement;
1128
1129            var messageWithXDocument = new MessageWithXDocument
1130            {
1131                Document = XDocument.Load(new StringReader(XmlDocument))
1132            };
1133            var messageWithXElement = new MessageWithXElement
1134            {
1135                Document = XElement.Load(new StringReader(XmlElement))
1136            };
1137
1138            var resultXDocument = ExecuteSerializer.ForMessage<MessageWithXDocument>(messageWithXDocument);
1139            var resultXElement = ExecuteSerializer.ForMessage<MessageWithXElement>(messageWithXElement);
1140
1141            Assert.AreEqual(messageWithXDocument.Document.ToString(), resultXDocument.Document.ToString());
1142            Assert.AreEqual(messageWithXElement.Document.ToString(), resultXElement.Document.ToString());
1143        }
1144
1145        [Test]
1146        public void Should_be_able_to_deserialize_many_messages_of_same_type()
1147        {
1148            var xml = @"<?xml version=""1.0"" ?>
1149<Messages xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://tempuri.net/NServiceBus.Serializers.XML.Test"">
1150    <EmptyMessage>
1151    </EmptyMessage>
1152    <EmptyMessage>
1153    </EmptyMessage>
1154    <EmptyMessage>
1155    </EmptyMessage>
1156</Messages>
1157";
1158            using (var stream = new MemoryStream())
1159            {
1160                var streamWriter = new StreamWriter(stream);
1161                streamWriter.Write(xml);
1162                streamWriter.Flush();
1163                stream.Position = 0;
1164                var serializer = SerializerFactory.Create<EmptyMessage>();
1165                var msgArray = serializer.Deserialize(stream, new[]
1166                {
1167                    typeof(EmptyMessage)
1168                });
1169                Assert.AreEqual(3, msgArray.Length);
1170            }
1171        }
1172
1173        [Test]
1174        public void Object_property_with_primitive_or_struct_value_should_serialize_correctly()
1175        {
1176            // this fixes issue #2796
1177
1178            var serializer = SerializerFactory.Create<SerializedPair>();
1179            var message = new SerializedPair
1180            {
1181                Key = "AddressId",
1182                Value = new Guid("{ebdeeb33-baa7-4100-b1aa-eb4d6816fd3d}")
1183            };
1184
1185            object[] messageDeserialized;
1186            using (var stream = new MemoryStream())
1187            {
1188                serializer.Serialize(message, stream);
1189
1190                stream.Position = 0;
1191
1192                messageDeserialized = serializer.Deserialize(stream, new[]
1193                {
1194                    message.GetType()
1195                });
1196            }
1197
1198            Assert.AreEqual(message.Key, ((SerializedPair)messageDeserialized[0]).Key);
1199            Assert.AreEqual(message.Value, ((SerializedPair)messageDeserialized[0]).Value);
1200        }
1201
1202        int number = 1;
1203        int numberOfIterations = 100;
1204    }
1205
1206    public class SerializedPair
1207    {
1208        public string Key { get; set; }
1209        public object Value { get; set; }
1210    }
1211
1212    public class EmptyMessage : IMessage
1213    {
1214    }
1215
1216    public struct StructMessage : IMessage
1217    {
1218        public string SomeProperty { get; set; }
1219
1220        public string SomeField;
1221    }
1222
1223    public class MessageWithStructProperty : IMessage
1224    {
1225        public SomeStruct StructProperty { get; set; }
1226
1227        public struct SomeStruct
1228        {
1229
1230        }
1231    }
1232
1233    public class PolyMessage : IMessage
1234    {
1235        public BaseType BaseType { get; set; }
1236    }
1237
1238    public class ChildOfBase : BaseType
1239    {
1240        public BaseType BaseType { get; set; }
1241
1242
1243        public string ChildProp { get; set; }
1244    }
1245
1246    public class BaseType
1247    {
1248        public string BaseTypeProp { get; set; }
1249    }
1250
1251    public class MessageWithGenericPropClosingNullable
1252    {
1253        public GenericPropertyWithNullable<DateTime?> GenericNullable { get; set; }
1254        public string Whatever { get; set; }
1255    }
1256
1257    public class MessageWithNullProperty
1258    {
1259        public string WillBeNull { get; set; }
1260    }
1261
1262    public class MessageWithDouble
1263    {
1264        public double Double { get; set; }
1265    }
1266
1267    public class MessageWithGenericProperty
1268    {
1269        public GenericProperty<string> GenericProperty { get; set; }
1270        public GenericProperty<string> GenericPropertyThatIsNull { get; set; }
1271    }
1272
1273    public class MessageWithNestedObject
1274    {
1275        public MessageWithNullProperty NestedObject { get; set; }
1276    }
1277
1278
1279    public class MessageWithSystemClassAsProperty
1280    {
1281        public MailMessage MailMessage { get; set; }
1282    }
1283
1284
1285    public class GenericPropertyWithNullable<T>
1286    {
1287        public T TheType { get; set; }
1288    }
1289
1290    public class GenericProperty<T>
1291    {
1292        public GenericProperty(T value)
1293        {
1294            ReadOnlyBlob = value;
1295        }
1296
1297        public T ReadOnlyBlob { get; }
1298
1299        public string WhatEver { get; set; }
1300    }
1301
1302    public class MessageWithDictionaryWithAnObjectAsKey
1303    {
1304        public Dictionary<object, string> Content { get; set; }
1305    }
1306
1307    public class MessageWithDictionaryWithAnObjectAsValue
1308    {
1309        public Dictionary<string, object> Content { get; set; }
1310    }
1311
1312    public class MessageWithListItem
1313    {
1314        public string Data { get; set; }
1315    }
1316
1317    public class MessageWithInvalidCharacter : IMessage
1318    {
1319        public string Special { get; set; }
1320    }
1321
1322    public class MessageWithList : IMessage
1323    {
1324        public List<MessageWithListItem> Items { get; set; }
1325    }
1326
1327
1328    public class MessageWithHashtable : IMessage
1329    {
1330        public Hashtable Hashtable { get; set; }
1331    }
1332
1333
1334    public class MessageWithArrayList : IMessage
1335    {
1336        public ArrayList ArrayList { get; set; }
1337    }
1338
1339    public class MessageWithClosedListInAlternateNamespace : IMessage
1340    {
1341        public AlternateItemList Items { get; set; }
1342    }
1343
1344    public class MessageWithClosedListInAlternateNamespaceMultipleIEnumerableImplementations : IMessage
1345    {
1346        public AlternateItemListMultipleIEnumerableImplementations Items { get; set; }
1347    }
1348
1349    public class MessageWithClosedListInAlternateNamespaceMultipleIListImplementations : IMessage
1350    {
1351        public AlternateItemListMultipleIListImplementations Items { get; set; }
1352    }
1353
1354    public class MessageWithClosedList : IMessage
1355    {
1356        public ItemList Items { get; set; }
1357    }
1358
1359
1360    public class MessageWithXDocument : IMessage
1361    {
1362        public XDocument Document { get; set; }
1363    }
1364
1365
1366    public class MessageWithXElement : IMessage
1367    {
1368        public XElement Document { get; set; }
1369    }
1370
1371    public class ItemList : List<MessageWithListItem>
1372    {
1373    }
1374
1375    public class CompositeMessage : IMyEventA, IMyEventB
1376    {
1377        public string StringValue { get; set; }
1378        public int IntValue { get; set; }
1379    }
1380
1381    public interface IMyEventA
1382    {
1383        string StringValue { get; set; }
1384    }
1385
1386    public class MyEventA_impl : IMyEventA
1387    {
1388        public string StringValue { get; set; }
1389    }
1390
1391    public interface IMyEventB
1392    {
1393        int IntValue { get; set; }
1394    }
1395
1396    public class MyEventB_impl : IMyEventB
1397    {
1398        public int IntValue { get; set; }
1399    }
1400}
1401
1402namespace NServiceBus.Serializers.XML.Test.AlternateNamespace
1403{
1404    using System.Collections.Generic;
1405    using System.Linq;
1406    using System.Runtime.Serialization;
1407
1408    public class AlternateItemList : List<MessageWithListItemAlternate>
1409    {
1410    }
1411
1412    public class MessageWithListItemAlternate
1413    {
1414        public string Data { get; set; }
1415    }
1416
1417    public class AlternateItemListMultipleIEnumerableImplementations : List<MessageWithListItemAlternate>, IEnumerable<string>
1418    {
1419        public new IEnumerator<string> GetEnumerator()
1420        {
1421            return ToArray().Select(item => item.Data).GetEnumerator();
1422        }
1423    }
1424
1425    public class AlternateItemListMultipleIListImplementations : List<MessageWithListItemAlternate>, IList<string>
1426    {
1427        IEnumerator<string> IEnumerable<string>.GetEnumerator()
1428        {
1429            return stringList.GetEnumerator();
1430        }
1431
1432        void ICollection<string>.Add(string item)
1433        {
1434            stringList.Add(item);
1435        }
1436
1437        bool ICollection<string>.Contains(string item)
1438        {
1439            return stringList.Contains(item);
1440        }
1441
1442        void ICollection<string>.CopyTo(string[] arra

Large files files are truncated, but you can click here to view the full file