2 // ConfigurationSaveTest.cs
5 // Martin Baulig <martin.baulig@xamarin.com>
7 // Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 using System.Xml.Schema;
30 using System.Xml.XPath;
32 using System.Reflection;
33 using System.Globalization;
34 using System.Configuration;
35 using System.Collections.Generic;
36 using SysConfig = System.Configuration.Configuration;
38 using NUnit.Framework;
39 using NUnit.Framework.Constraints;
41 namespace MonoTests.System.Configuration {
45 public class ConfigurationSaveTest {
47 #region Test Framework
49 public abstract class ConfigProvider {
50 public void Create (string filename)
52 if (File.Exists (filename))
53 File.Delete (filename);
55 var settings = new XmlWriterSettings ();
56 settings.Indent = true;
58 using (var writer = XmlTextWriter.Create (filename, settings)) {
59 writer.WriteStartElement ("configuration");
61 writer.WriteEndElement ();
65 public abstract UserLevel Level {
69 public enum UserLevel {
74 public virtual SysConfig OpenConfig (string parentFile, string configFile)
76 ConfigurationUserLevel level;
77 var map = new ExeConfigurationFileMap ();
79 case UserLevel.MachineAndExe:
80 map.ExeConfigFilename = configFile;
81 map.MachineConfigFilename = parentFile;
82 level = ConfigurationUserLevel.None;
84 case UserLevel.RoamingAndExe:
85 map.RoamingUserConfigFilename = configFile;
86 map.ExeConfigFilename = parentFile;
87 level = ConfigurationUserLevel.PerUserRoaming;
90 throw new InvalidOperationException ();
93 return ConfigurationManager.OpenMappedExeConfiguration (map, level);
96 protected abstract void WriteXml (XmlWriter writer);
99 public abstract class MachineConfigProvider : ConfigProvider {
100 protected override void WriteXml (XmlWriter writer)
102 writer.WriteStartElement ("configSections");
103 WriteSections (writer);
104 writer.WriteEndElement ();
105 WriteValues (writer);
108 public override UserLevel Level {
109 get { return UserLevel.MachineAndExe; }
112 protected abstract void WriteSections (XmlWriter writer);
114 protected abstract void WriteValues (XmlWriter writer);
117 class DefaultMachineConfig : MachineConfigProvider {
118 protected override void WriteSections (XmlWriter writer)
120 writer.WriteStartElement ("section");
121 writer.WriteAttributeString ("name", "my");
122 writer.WriteAttributeString ("type", typeof (MySection).AssemblyQualifiedName);
123 writer.WriteAttributeString ("allowLocation", "true");
124 writer.WriteAttributeString ("allowDefinition", "Everywhere");
125 writer.WriteAttributeString ("allowExeDefinition", "MachineToRoamingUser");
126 writer.WriteAttributeString ("restartOnExternalChanges", "true");
127 writer.WriteAttributeString ("requirePermission", "true");
128 writer.WriteEndElement ();
131 internal static void WriteConfigSections (XmlWriter writer)
133 var provider = new DefaultMachineConfig ();
134 writer.WriteStartElement ("configSections");
135 provider.WriteSections (writer);
136 writer.WriteEndElement ();
139 protected override void WriteValues (XmlWriter writer)
141 writer.WriteStartElement ("my");
142 writer.WriteEndElement ();
146 class DefaultMachineConfig2 : MachineConfigProvider {
147 protected override void WriteSections (XmlWriter writer)
149 writer.WriteStartElement ("section");
150 writer.WriteAttributeString ("name", "my2");
151 writer.WriteAttributeString ("type", typeof (MySection2).AssemblyQualifiedName);
152 writer.WriteAttributeString ("allowLocation", "true");
153 writer.WriteAttributeString ("allowDefinition", "Everywhere");
154 writer.WriteAttributeString ("allowExeDefinition", "MachineToRoamingUser");
155 writer.WriteAttributeString ("restartOnExternalChanges", "true");
156 writer.WriteAttributeString ("requirePermission", "true");
157 writer.WriteEndElement ();
160 internal static void WriteConfigSections (XmlWriter writer)
162 var provider = new DefaultMachineConfig2 ();
163 writer.WriteStartElement ("configSections");
164 provider.WriteSections (writer);
165 writer.WriteEndElement ();
168 protected override void WriteValues (XmlWriter writer)
173 abstract class ParentProvider : ConfigProvider {
174 protected override void WriteXml (XmlWriter writer)
176 DefaultMachineConfig.WriteConfigSections (writer);
177 writer.WriteStartElement ("my");
178 writer.WriteStartElement ("test");
179 writer.WriteAttributeString ("Hello", "29");
180 writer.WriteEndElement ();
181 writer.WriteEndElement ();
185 class RoamingAndExe : ParentProvider {
186 public override UserLevel Level {
187 get { return UserLevel.RoamingAndExe; }
191 public delegate void TestFunction (SysConfig config, TestLabel label);
192 public delegate void XmlCheckFunction (XPathNavigator nav, TestLabel label);
194 public static void Run (string name, TestFunction func)
196 var label = new TestLabel (name);
198 TestUtil.RunWithTempFile (filename => {
199 var fileMap = new ExeConfigurationFileMap ();
200 fileMap.ExeConfigFilename = filename;
201 var config = ConfigurationManager.OpenMappedExeConfiguration (
202 fileMap, ConfigurationUserLevel.None);
204 func (config, label);
208 public static void Run<TConfig> (string name, TestFunction func)
209 where TConfig : ConfigProvider, new ()
211 Run<TConfig> (new TestLabel (name), func, null);
214 public static void Run<TConfig> (TestLabel label, TestFunction func)
215 where TConfig : ConfigProvider, new ()
217 Run<TConfig> (label, func, null);
220 public static void Run<TConfig> (
221 string name, TestFunction func, XmlCheckFunction check)
222 where TConfig : ConfigProvider, new ()
224 Run<TConfig> (new TestLabel (name), func, check);
227 public static void Run<TConfig> (
228 TestLabel label, TestFunction func, XmlCheckFunction check)
229 where TConfig : ConfigProvider, new ()
231 TestUtil.RunWithTempFiles ((parent,filename) => {
232 var provider = new TConfig ();
233 provider.Create (parent);
235 Assert.That (File.Exists (filename), Is.False);
237 var config = provider.OpenConfig (parent, filename);
239 Assert.That (File.Exists (filename), Is.False);
242 label.EnterScope ("config");
243 func (config, label);
251 var xml = new XmlDocument ();
254 var nav = xml.CreateNavigator ().SelectSingleNode ("/configuration");
256 label.EnterScope ("xml");
266 #region Assertion Helpers
268 static void AssertNotModified (MySection my, TestLabel label)
270 label.EnterScope ("modified");
271 Assert.That (my, Is.Not.Null, label.Get ());
272 Assert.That (my.IsModified, Is.False, label.Get ());
273 Assert.That (my.List, Is.Not.Null, label.Get ());
274 Assert.That (my.List.Collection.Count, Is.EqualTo (0), label.Get ());
275 Assert.That (my.List.IsModified, Is.False, label.Get ());
279 static void AssertListElement (XPathNavigator nav, TestLabel label)
281 Assert.That (nav.HasChildren, Is.True, label.Get ());
282 var iter = nav.SelectChildren (XPathNodeType.Element);
284 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
285 Assert.That (iter.MoveNext (), Is.True, label.Get ());
287 var my = iter.Current;
288 label.EnterScope ("my");
289 Assert.That (my.Name, Is.EqualTo ("my"), label.Get ());
290 Assert.That (my.HasAttributes, Is.False, label.Get ());
292 label.EnterScope ("children");
293 Assert.That (my.HasChildren, Is.True, label.Get ());
294 var iter2 = my.SelectChildren (XPathNodeType.Element);
295 Assert.That (iter2.Count, Is.EqualTo (1), label.Get ());
296 Assert.That (iter2.MoveNext (), Is.True, label.Get ());
298 var test = iter2.Current;
299 label.EnterScope ("test");
300 Assert.That (test.Name, Is.EqualTo ("test"), label.Get ());
301 Assert.That (test.HasChildren, Is.False, label.Get ());
302 Assert.That (test.HasAttributes, Is.True, label.Get ());
304 var attr = test.GetAttribute ("Hello", string.Empty);
305 Assert.That (attr, Is.EqualTo ("29"), label.Get ());
316 public void DefaultValues ()
318 Run<DefaultMachineConfig> ("DefaultValues", (config,label) => {
319 var my = config.Sections ["my"] as MySection;
321 AssertNotModified (my, label);
323 label.EnterScope ("file");
324 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
326 config.Save (ConfigurationSaveMode.Minimal);
327 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
333 public void AddDefaultListElement ()
335 Run<DefaultMachineConfig> ("AddDefaultListElement", (config,label) => {
336 var my = config.Sections ["my"] as MySection;
338 AssertNotModified (my, label);
340 label.EnterScope ("add");
341 var element = my.List.Collection.AddElement ();
342 Assert.That (my.IsModified, Is.True, label.Get ());
343 Assert.That (my.List.IsModified, Is.True, label.Get ());
344 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
345 Assert.That (element.IsModified, Is.False, label.Get ());
348 config.Save (ConfigurationSaveMode.Minimal);
349 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
354 public void AddDefaultListElement2 ()
356 Run<DefaultMachineConfig> ("AddDefaultListElement2", (config,label) => {
357 var my = config.Sections ["my"] as MySection;
359 AssertNotModified (my, label);
361 label.EnterScope ("add");
362 var element = my.List.Collection.AddElement ();
363 Assert.That (my.IsModified, Is.True, label.Get ());
364 Assert.That (my.List.IsModified, Is.True, label.Get ());
365 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
366 Assert.That (element.IsModified, Is.False, label.Get ());
369 config.Save (ConfigurationSaveMode.Modified);
370 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
372 Assert.That (nav.HasChildren, Is.True, label.Get ());
373 var iter = nav.SelectChildren (XPathNodeType.Element);
375 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
376 Assert.That (iter.MoveNext (), Is.True, label.Get ());
378 var my = iter.Current;
379 label.EnterScope ("my");
380 Assert.That (my.Name, Is.EqualTo ("my"), label.Get ());
381 Assert.That (my.HasAttributes, Is.False, label.Get ());
382 Assert.That (my.HasChildren, Is.False, label.Get ());
388 public void AddDefaultListElement3 ()
390 Run<DefaultMachineConfig> ("AddDefaultListElement3", (config,label) => {
391 var my = config.Sections ["my"] as MySection;
393 AssertNotModified (my, label);
395 label.EnterScope ("add");
396 var element = my.List.Collection.AddElement ();
397 Assert.That (my.IsModified, Is.True, label.Get ());
398 Assert.That (my.List.IsModified, Is.True, label.Get ());
399 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
400 Assert.That (element.IsModified, Is.False, label.Get ());
403 config.Save (ConfigurationSaveMode.Full);
404 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
406 Assert.That (nav.HasChildren, Is.True, label.Get ());
407 var iter = nav.SelectChildren (XPathNodeType.Element);
409 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
410 Assert.That (iter.MoveNext (), Is.True, label.Get ());
412 var my = iter.Current;
413 label.EnterScope ("my");
414 Assert.That (my.Name, Is.EqualTo ("my"), label.Get ());
415 Assert.That (my.HasAttributes, Is.False, label.Get ());
417 label.EnterScope ("children");
418 Assert.That (my.HasChildren, Is.True, label.Get ());
419 var iter2 = my.SelectChildren (XPathNodeType.Element);
420 Assert.That (iter2.Count, Is.EqualTo (2), label.Get ());
422 label.EnterScope ("list");
423 var iter3 = my.Select ("list/*");
424 Assert.That (iter3.Count, Is.EqualTo (1), label.Get ());
425 Assert.That (iter3.MoveNext (), Is.True, label.Get ());
426 var collection = iter3.Current;
427 Assert.That (collection.Name, Is.EqualTo ("collection"), label.Get ());
428 Assert.That (collection.HasChildren, Is.False, label.Get ());
429 Assert.That (collection.HasAttributes, Is.True, label.Get ());
430 var hello = collection.GetAttribute ("Hello", string.Empty);
431 Assert.That (hello, Is.EqualTo ("8"), label.Get ());
432 var world = collection.GetAttribute ("World", string.Empty);
433 Assert.That (world, Is.EqualTo ("0"), label.Get ());
436 label.EnterScope ("test");
437 var iter4 = my.Select ("test");
438 Assert.That (iter4.Count, Is.EqualTo (1), label.Get ());
439 Assert.That (iter4.MoveNext (), Is.True, label.Get ());
440 var test = iter4.Current;
441 Assert.That (test.Name, Is.EqualTo ("test"), label.Get ());
442 Assert.That (test.HasChildren, Is.False, label.Get ());
443 Assert.That (test.HasAttributes, Is.True, label.Get ());
445 var hello2 = test.GetAttribute ("Hello", string.Empty);
446 Assert.That (hello2, Is.EqualTo ("8"), label.Get ());
447 var world2 = test.GetAttribute ("World", string.Empty);
448 Assert.That (world2, Is.EqualTo ("0"), label.Get ());
456 public void AddListElement ()
458 Run<DefaultMachineConfig> ("AddListElement", (config,label) => {
459 var my = config.Sections ["my"] as MySection;
461 AssertNotModified (my, label);
465 label.EnterScope ("file");
466 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
468 config.Save (ConfigurationSaveMode.Minimal);
469 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
472 AssertListElement (nav, label);
477 public void NotModifiedAfterSave ()
479 Run<DefaultMachineConfig> ("NotModifiedAfterSave", (config,label) => {
480 var my = config.Sections ["my"] as MySection;
482 AssertNotModified (my, label);
484 label.EnterScope ("add");
485 var element = my.List.Collection.AddElement ();
486 Assert.That (my.IsModified, Is.True, label.Get ());
487 Assert.That (my.List.IsModified, Is.True, label.Get ());
488 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
489 Assert.That (element.IsModified, Is.False, label.Get ());
492 label.EnterScope ("1st-save");
493 config.Save (ConfigurationSaveMode.Minimal);
494 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
495 config.Save (ConfigurationSaveMode.Modified);
496 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
499 label.EnterScope ("modify");
501 Assert.That (my.IsModified, Is.True, label.Get ());
502 Assert.That (my.List.IsModified, Is.True, label.Get ());
503 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
504 Assert.That (element.IsModified, Is.True, label.Get ());
507 label.EnterScope ("2nd-save");
508 config.Save (ConfigurationSaveMode.Modified);
509 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
511 Assert.That (my.IsModified, Is.False, label.Get ());
512 Assert.That (my.List.IsModified, Is.False, label.Get ());
513 Assert.That (my.List.Collection.IsModified, Is.False, label.Get ());
514 Assert.That (element.IsModified, Is.False, label.Get ());
515 label.LeaveScope (); // 2nd-save
520 public void AddSection ()
522 Run ("AddSection", (config,label) => {
523 Assert.That (config.Sections ["my"], Is.Null, label.Get ());
525 var my = new MySection ();
526 config.Sections.Add ("my2", my);
527 config.Save (ConfigurationSaveMode.Full);
529 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
534 public void AddElement ()
536 Run<DefaultMachineConfig> ("AddElement", (config,label) => {
537 var my = config.Sections ["my"] as MySection;
539 AssertNotModified (my, label);
541 var element = my.List.DefaultCollection.AddElement ();
544 config.Save (ConfigurationSaveMode.Modified);
546 label.EnterScope ("file");
547 Assert.That (File.Exists (config.FilePath), Is.True, "#c2");
550 Assert.That (nav.HasChildren, Is.True, label.Get ());
551 var iter = nav.SelectChildren (XPathNodeType.Element);
553 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
554 Assert.That (iter.MoveNext (), Is.True, label.Get ());
556 var my = iter.Current;
557 label.EnterScope ("my");
558 Assert.That (my.Name, Is.EqualTo ("my"), label.Get ());
559 Assert.That (my.HasAttributes, Is.False, label.Get ());
560 Assert.That (my.HasChildren, Is.True, label.Get ());
562 label.EnterScope ("children");
563 var iter2 = my.SelectChildren (XPathNodeType.Element);
564 Assert.That (iter2.Count, Is.EqualTo (1), label.Get ());
565 Assert.That (iter2.MoveNext (), Is.True, label.Get ());
567 var list = iter2.Current;
568 label.EnterScope ("list");
569 Assert.That (list.Name, Is.EqualTo ("list"), label.Get ());
570 Assert.That (list.HasChildren, Is.False, label.Get ());
571 Assert.That (list.HasAttributes, Is.True, label.Get ());
573 var attr = list.GetAttribute ("Hello", string.Empty);
574 Assert.That (attr, Is.EqualTo ("12"), label.Get ());
582 public void ModifyListElement ()
584 Run<RoamingAndExe> ("ModifyListElement", (config,label) => {
585 var my = config.Sections ["my"] as MySection;
587 AssertNotModified (my, label);
591 label.EnterScope ("file");
592 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
594 config.Save (ConfigurationSaveMode.Minimal);
595 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
601 public void ModifyListElement2 ()
603 Run<RoamingAndExe> ("ModifyListElement2", (config,label) => {
604 var my = config.Sections ["my"] as MySection;
606 AssertNotModified (my, label);
610 label.EnterScope ("file");
611 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
613 config.Save (ConfigurationSaveMode.Modified);
614 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
617 AssertListElement (nav, label);
622 public void TestElementWithCollection ()
624 Run<DefaultMachineConfig2> ("TestElementWithCollection", (config,label) => {
625 label.EnterScope ("section");
626 var my2 = config.Sections ["my2"] as MySection2;
627 Assert.That (my2, Is.Not.Null, label.Get ());
629 Assert.That (my2.Test, Is.Not.Null, label.Get ());
630 Assert.That (my2.Test.DefaultCollection, Is.Not.Null, label.Get ());
631 Assert.That (my2.Test.DefaultCollection.Count, Is.EqualTo (0), label.Get ());
634 my2.Test.DefaultCollection.AddElement ();
636 my2.Element.Hello = 29;
638 label.EnterScope ("file");
639 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
641 config.Save (ConfigurationSaveMode.Minimal);
642 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
645 Console.WriteLine (nav.OuterXml);
646 Assert.That (nav.HasChildren, Is.True, label.Get ());
647 var iter = nav.SelectChildren (XPathNodeType.Element);
649 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
650 Assert.That (iter.MoveNext (), Is.True, label.Get ());
652 var my = iter.Current;
653 label.EnterScope ("my2");
654 Assert.That (my.Name, Is.EqualTo ("my2"), label.Get ());
655 Assert.That (my.HasAttributes, Is.False, label.Get ());
656 Assert.That (my.HasChildren, Is.True, label.Get ());
658 label.EnterScope ("children");
659 var iter2 = my.SelectChildren (XPathNodeType.Element);
660 Assert.That (iter2.Count, Is.EqualTo (1), label.Get ());
661 Assert.That (iter2.MoveNext (), Is.True, label.Get ());
663 var element = iter2.Current;
664 label.EnterScope ("element");
665 Assert.That (element.Name, Is.EqualTo ("element"), label.Get ());
666 Assert.That (element.HasChildren, Is.False, label.Get ());
667 Assert.That (element.HasAttributes, Is.True, label.Get ());
669 var attr = element.GetAttribute ("Hello", string.Empty);
670 Assert.That (attr, Is.EqualTo ("29"), label.Get ());
678 public void TestElementWithCollection2 ()
680 Run<DefaultMachineConfig2> ("TestElementWithCollection2", (config,label) => {
681 label.EnterScope ("section");
682 var my2 = config.Sections ["my2"] as MySection2;
683 Assert.That (my2, Is.Not.Null, label.Get ());
685 Assert.That (my2.Test, Is.Not.Null, label.Get ());
686 Assert.That (my2.Test.DefaultCollection, Is.Not.Null, label.Get ());
687 Assert.That (my2.Test.DefaultCollection.Count, Is.EqualTo (0), label.Get ());
690 var element = my2.Test.DefaultCollection.AddElement ();
691 var element2 = element.Test.DefaultCollection.AddElement ();
694 label.EnterScope ("file");
695 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
697 config.Save (ConfigurationSaveMode.Minimal);
698 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
701 Console.WriteLine (nav.OuterXml);
702 Assert.That (nav.HasChildren, Is.True, label.Get ());
703 var iter = nav.SelectChildren (XPathNodeType.Element);
705 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
706 Assert.That (iter.MoveNext (), Is.True, label.Get ());
708 var my = iter.Current;
709 label.EnterScope ("my2");
710 Assert.That (my.Name, Is.EqualTo ("my2"), label.Get ());
711 Assert.That (my.HasAttributes, Is.False, label.Get ());
712 Assert.That (my.HasChildren, Is.True, label.Get ());
714 label.EnterScope ("children");
715 var iter2 = my.SelectChildren (XPathNodeType.Element);
716 Assert.That (iter2.Count, Is.EqualTo (1), label.Get ());
717 Assert.That (iter2.MoveNext (), Is.True, label.Get ());
719 var collection = iter2.Current;
720 label.EnterScope ("collection");
721 Assert.That (collection.Name, Is.EqualTo ("collection"), label.Get ());
722 Assert.That (collection.HasChildren, Is.True, label.Get ());
723 Assert.That (collection.HasAttributes, Is.False, label.Get ());
725 label.EnterScope ("children");
726 var iter3 = collection.SelectChildren (XPathNodeType.Element);
727 Assert.That (iter3.Count, Is.EqualTo (1), label.Get ());
728 Assert.That (iter3.MoveNext (), Is.True, label.Get ());
730 var element = iter3.Current;
731 label.EnterScope ("element");
732 Assert.That (element.Name, Is.EqualTo ("test"), label.Get ());
733 Assert.That (element.HasChildren, Is.False, label.Get ());
734 Assert.That (element.HasAttributes, Is.True, label.Get ());
736 var attr = element.GetAttribute ("Hello", string.Empty);
737 Assert.That (attr, Is.EqualTo ("1"), label.Get ());
748 #region Configuration Classes
750 public class MyElement : ConfigurationElement {
751 [ConfigurationProperty ("Hello", DefaultValue = 8)]
753 get { return (int)base ["Hello"]; }
754 set { base ["Hello"] = value; }
757 [ConfigurationProperty ("World", IsRequired = false)]
759 get { return (int)base ["World"]; }
760 set { base ["World"] = value; }
763 new public bool IsModified {
764 get { return base.IsModified (); }
768 public class MyCollection<T> : ConfigurationElementCollection
769 where T : ConfigurationElement, new ()
771 #region implemented abstract members of ConfigurationElementCollection
772 protected override ConfigurationElement CreateNewElement ()
776 protected override object GetElementKey (ConfigurationElement element)
778 return ((T)element).GetHashCode ();
782 public override ConfigurationElementCollectionType CollectionType {
784 return ConfigurationElementCollectionType.BasicMap;
788 public T AddElement ()
790 var element = new T ();
795 public void RemoveElement (T element)
797 BaseRemove (GetElementKey (element));
800 public new bool IsModified {
801 get { return base.IsModified (); }
805 public class MyCollectionElement<T> : ConfigurationElement
806 where T : ConfigurationElement, new ()
808 [ConfigurationProperty ("",
809 Options = ConfigurationPropertyOptions.IsDefaultCollection,
810 IsDefaultCollection = true)]
811 public MyCollection<T> DefaultCollection {
812 get { return (MyCollection<T>)this [String.Empty]; }
813 set { this [String.Empty] = value; }
816 [ConfigurationProperty ("collection", Options = ConfigurationPropertyOptions.None)]
817 public MyCollection<T> Collection {
818 get { return (MyCollection<T>)this ["collection"]; }
819 set { this ["collection"] = value; }
822 public new bool IsModified {
823 get { return base.IsModified (); }
827 public class MySection : ConfigurationSection {
828 [ConfigurationProperty ("list", Options = ConfigurationPropertyOptions.None)]
829 public MyCollectionElement<MyElement> List {
830 get { return (MyCollectionElement<MyElement>) this ["list"]; }
833 [ConfigurationProperty ("test", Options = ConfigurationPropertyOptions.None)]
834 public MyElement Test {
835 get { return (MyElement) this ["test"]; }
838 new public bool IsModified {
839 get { return base.IsModified (); }
844 public class MyElementWithCollection : ConfigurationElement {
845 [ConfigurationProperty ("test")]
846 public MyCollectionElement<MyElement> Test {
847 get { return (MyCollectionElement<MyElement>) this ["test"]; }
851 public class MySection2 : ConfigurationSection {
852 [ConfigurationProperty ("collection", Options = ConfigurationPropertyOptions.None)]
853 public MyCollectionElement<MyElementWithCollection> Test {
854 get { return (MyCollectionElement<MyElementWithCollection>) this ["collection"]; }
857 [ConfigurationProperty ("element", Options = ConfigurationPropertyOptions.None)]
858 public MyElement Element {
859 get { return (MyElement)this ["element"]; }
863 public class MySectionGroup : ConfigurationSectionGroup {
864 public MySection2 My2 {
865 get { return (MySection2)Sections ["my2"]; }