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;
40 using NUnit.Framework.SyntaxHelpers;
42 namespace MonoTests.System.Configuration {
46 public class ConfigurationSaveTest {
48 #region Test Framework
50 public abstract class ConfigProvider {
51 public void Create (string filename)
53 if (File.Exists (filename))
54 File.Delete (filename);
56 var settings = new XmlWriterSettings ();
57 settings.Indent = true;
59 using (var writer = XmlTextWriter.Create (filename, settings)) {
60 writer.WriteStartElement ("configuration");
62 writer.WriteEndElement ();
66 public abstract UserLevel Level {
70 public enum UserLevel {
75 public virtual SysConfig OpenConfig (string parentFile, string configFile)
77 ConfigurationUserLevel level;
78 var map = new ExeConfigurationFileMap ();
80 case UserLevel.MachineAndExe:
81 map.ExeConfigFilename = configFile;
82 map.MachineConfigFilename = parentFile;
83 level = ConfigurationUserLevel.None;
85 case UserLevel.RoamingAndExe:
86 map.RoamingUserConfigFilename = configFile;
87 map.ExeConfigFilename = parentFile;
88 level = ConfigurationUserLevel.PerUserRoaming;
91 throw new InvalidOperationException ();
94 return ConfigurationManager.OpenMappedExeConfiguration (map, level);
97 protected abstract void WriteXml (XmlWriter writer);
100 public abstract class MachineConfigProvider : ConfigProvider {
101 protected override void WriteXml (XmlWriter writer)
103 writer.WriteStartElement ("configSections");
104 WriteSections (writer);
105 writer.WriteEndElement ();
106 WriteValues (writer);
109 public override UserLevel Level {
110 get { return UserLevel.MachineAndExe; }
113 protected abstract void WriteSections (XmlWriter writer);
115 protected abstract void WriteValues (XmlWriter writer);
118 class DefaultMachineConfig : MachineConfigProvider {
119 protected override void WriteSections (XmlWriter writer)
121 writer.WriteStartElement ("section");
122 writer.WriteAttributeString ("name", "my");
123 writer.WriteAttributeString ("type", typeof (MySection).AssemblyQualifiedName);
124 writer.WriteAttributeString ("allowLocation", "true");
125 writer.WriteAttributeString ("allowDefinition", "Everywhere");
126 writer.WriteAttributeString ("allowExeDefinition", "MachineToRoamingUser");
127 writer.WriteAttributeString ("restartOnExternalChanges", "true");
128 writer.WriteAttributeString ("requirePermission", "true");
129 writer.WriteEndElement ();
132 internal static void WriteConfigSections (XmlWriter writer)
134 var provider = new DefaultMachineConfig ();
135 writer.WriteStartElement ("configSections");
136 provider.WriteSections (writer);
137 writer.WriteEndElement ();
140 protected override void WriteValues (XmlWriter writer)
142 writer.WriteStartElement ("my");
143 writer.WriteEndElement ();
147 class DefaultMachineConfig2 : MachineConfigProvider {
148 protected override void WriteSections (XmlWriter writer)
150 writer.WriteStartElement ("section");
151 writer.WriteAttributeString ("name", "my2");
152 writer.WriteAttributeString ("type", typeof (MySection2).AssemblyQualifiedName);
153 writer.WriteAttributeString ("allowLocation", "true");
154 writer.WriteAttributeString ("allowDefinition", "Everywhere");
155 writer.WriteAttributeString ("allowExeDefinition", "MachineToRoamingUser");
156 writer.WriteAttributeString ("restartOnExternalChanges", "true");
157 writer.WriteAttributeString ("requirePermission", "true");
158 writer.WriteEndElement ();
161 internal static void WriteConfigSections (XmlWriter writer)
163 var provider = new DefaultMachineConfig2 ();
164 writer.WriteStartElement ("configSections");
165 provider.WriteSections (writer);
166 writer.WriteEndElement ();
169 protected override void WriteValues (XmlWriter writer)
174 abstract class ParentProvider : ConfigProvider {
175 protected override void WriteXml (XmlWriter writer)
177 DefaultMachineConfig.WriteConfigSections (writer);
178 writer.WriteStartElement ("my");
179 writer.WriteStartElement ("test");
180 writer.WriteAttributeString ("Hello", "29");
181 writer.WriteEndElement ();
182 writer.WriteEndElement ();
186 class RoamingAndExe : ParentProvider {
187 public override UserLevel Level {
188 get { return UserLevel.RoamingAndExe; }
192 public delegate void TestFunction (SysConfig config, TestLabel label);
193 public delegate void XmlCheckFunction (XPathNavigator nav, TestLabel label);
195 public static void Run (string name, TestFunction func)
197 var label = new TestLabel (name);
199 TestUtil.RunWithTempFile (filename => {
200 var fileMap = new ExeConfigurationFileMap ();
201 fileMap.ExeConfigFilename = filename;
202 var config = ConfigurationManager.OpenMappedExeConfiguration (
203 fileMap, ConfigurationUserLevel.None);
205 func (config, label);
209 public static void Run<TConfig> (string name, TestFunction func)
210 where TConfig : ConfigProvider, new ()
212 Run<TConfig> (new TestLabel (name), func, null);
215 public static void Run<TConfig> (TestLabel label, TestFunction func)
216 where TConfig : ConfigProvider, new ()
218 Run<TConfig> (label, func, null);
221 public static void Run<TConfig> (
222 string name, TestFunction func, XmlCheckFunction check)
223 where TConfig : ConfigProvider, new ()
225 Run<TConfig> (new TestLabel (name), func, check);
228 public static void Run<TConfig> (
229 TestLabel label, TestFunction func, XmlCheckFunction check)
230 where TConfig : ConfigProvider, new ()
232 TestUtil.RunWithTempFiles ((parent,filename) => {
233 var provider = new TConfig ();
234 provider.Create (parent);
236 Assert.That (File.Exists (filename), Is.False);
238 var config = provider.OpenConfig (parent, filename);
240 Assert.That (File.Exists (filename), Is.False);
243 label.EnterScope ("config");
244 func (config, label);
252 var xml = new XmlDocument ();
255 var nav = xml.CreateNavigator ().SelectSingleNode ("/configuration");
257 label.EnterScope ("xml");
267 #region Assertion Helpers
269 static void AssertNotModified (MySection my, TestLabel label)
271 label.EnterScope ("modified");
272 Assert.That (my, Is.Not.Null, label.Get ());
273 Assert.That (my.IsModified, Is.False, label.Get ());
274 Assert.That (my.List, Is.Not.Null, label.Get ());
275 Assert.That (my.List.Collection.Count, Is.EqualTo (0), label.Get ());
276 Assert.That (my.List.IsModified, Is.False, label.Get ());
280 static void AssertListElement (XPathNavigator nav, TestLabel label)
282 Assert.That (nav.HasChildren, Is.True, label.Get ());
283 var iter = nav.SelectChildren (XPathNodeType.Element);
285 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
286 Assert.That (iter.MoveNext (), Is.True, label.Get ());
288 var my = iter.Current;
289 label.EnterScope ("my");
290 Assert.That (my.Name, Is.EqualTo ("my"), label.Get ());
291 Assert.That (my.HasAttributes, Is.False, label.Get ());
293 label.EnterScope ("children");
294 Assert.That (my.HasChildren, Is.True, label.Get ());
295 var iter2 = my.SelectChildren (XPathNodeType.Element);
296 Assert.That (iter2.Count, Is.EqualTo (1), label.Get ());
297 Assert.That (iter2.MoveNext (), Is.True, label.Get ());
299 var test = iter2.Current;
300 label.EnterScope ("test");
301 Assert.That (test.Name, Is.EqualTo ("test"), label.Get ());
302 Assert.That (test.HasChildren, Is.False, label.Get ());
303 Assert.That (test.HasAttributes, Is.True, label.Get ());
305 var attr = test.GetAttribute ("Hello", string.Empty);
306 Assert.That (attr, Is.EqualTo ("29"), label.Get ());
317 public void DefaultValues ()
319 Run<DefaultMachineConfig> ("DefaultValues", (config,label) => {
320 var my = config.Sections ["my"] as MySection;
322 AssertNotModified (my, label);
324 label.EnterScope ("file");
325 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
327 config.Save (ConfigurationSaveMode.Minimal);
328 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
334 public void AddDefaultListElement ()
336 Run<DefaultMachineConfig> ("AddDefaultListElement", (config,label) => {
337 var my = config.Sections ["my"] as MySection;
339 AssertNotModified (my, label);
341 label.EnterScope ("add");
342 var element = my.List.Collection.AddElement ();
343 Assert.That (my.IsModified, Is.True, label.Get ());
344 Assert.That (my.List.IsModified, Is.True, label.Get ());
345 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
346 Assert.That (element.IsModified, Is.False, label.Get ());
349 config.Save (ConfigurationSaveMode.Minimal);
350 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
355 public void AddDefaultListElement2 ()
357 Run<DefaultMachineConfig> ("AddDefaultListElement2", (config,label) => {
358 var my = config.Sections ["my"] as MySection;
360 AssertNotModified (my, label);
362 label.EnterScope ("add");
363 var element = my.List.Collection.AddElement ();
364 Assert.That (my.IsModified, Is.True, label.Get ());
365 Assert.That (my.List.IsModified, Is.True, label.Get ());
366 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
367 Assert.That (element.IsModified, Is.False, label.Get ());
370 config.Save (ConfigurationSaveMode.Modified);
371 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
373 Assert.That (nav.HasChildren, Is.True, label.Get ());
374 var iter = nav.SelectChildren (XPathNodeType.Element);
376 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
377 Assert.That (iter.MoveNext (), Is.True, label.Get ());
379 var my = iter.Current;
380 label.EnterScope ("my");
381 Assert.That (my.Name, Is.EqualTo ("my"), label.Get ());
382 Assert.That (my.HasAttributes, Is.False, label.Get ());
383 Assert.That (my.HasChildren, Is.False, label.Get ());
389 public void AddDefaultListElement3 ()
391 Run<DefaultMachineConfig> ("AddDefaultListElement3", (config,label) => {
392 var my = config.Sections ["my"] as MySection;
394 AssertNotModified (my, label);
396 label.EnterScope ("add");
397 var element = my.List.Collection.AddElement ();
398 Assert.That (my.IsModified, Is.True, label.Get ());
399 Assert.That (my.List.IsModified, Is.True, label.Get ());
400 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
401 Assert.That (element.IsModified, Is.False, label.Get ());
404 config.Save (ConfigurationSaveMode.Full);
405 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
407 Assert.That (nav.HasChildren, Is.True, label.Get ());
408 var iter = nav.SelectChildren (XPathNodeType.Element);
410 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
411 Assert.That (iter.MoveNext (), Is.True, label.Get ());
413 var my = iter.Current;
414 label.EnterScope ("my");
415 Assert.That (my.Name, Is.EqualTo ("my"), label.Get ());
416 Assert.That (my.HasAttributes, Is.False, label.Get ());
418 label.EnterScope ("children");
419 Assert.That (my.HasChildren, Is.True, label.Get ());
420 var iter2 = my.SelectChildren (XPathNodeType.Element);
421 Assert.That (iter2.Count, Is.EqualTo (2), label.Get ());
423 label.EnterScope ("list");
424 var iter3 = my.Select ("list/*");
425 Assert.That (iter3.Count, Is.EqualTo (1), label.Get ());
426 Assert.That (iter3.MoveNext (), Is.True, label.Get ());
427 var collection = iter3.Current;
428 Assert.That (collection.Name, Is.EqualTo ("collection"), label.Get ());
429 Assert.That (collection.HasChildren, Is.False, label.Get ());
430 Assert.That (collection.HasAttributes, Is.True, label.Get ());
431 var hello = collection.GetAttribute ("Hello", string.Empty);
432 Assert.That (hello, Is.EqualTo ("8"), label.Get ());
433 var world = collection.GetAttribute ("World", string.Empty);
434 Assert.That (world, Is.EqualTo ("0"), label.Get ());
437 label.EnterScope ("test");
438 var iter4 = my.Select ("test");
439 Assert.That (iter4.Count, Is.EqualTo (1), label.Get ());
440 Assert.That (iter4.MoveNext (), Is.True, label.Get ());
441 var test = iter4.Current;
442 Assert.That (test.Name, Is.EqualTo ("test"), label.Get ());
443 Assert.That (test.HasChildren, Is.False, label.Get ());
444 Assert.That (test.HasAttributes, Is.True, label.Get ());
446 var hello2 = test.GetAttribute ("Hello", string.Empty);
447 Assert.That (hello2, Is.EqualTo ("8"), label.Get ());
448 var world2 = test.GetAttribute ("World", string.Empty);
449 Assert.That (world2, Is.EqualTo ("0"), label.Get ());
457 public void AddListElement ()
459 Run<DefaultMachineConfig> ("AddListElement", (config,label) => {
460 var my = config.Sections ["my"] as MySection;
462 AssertNotModified (my, label);
466 label.EnterScope ("file");
467 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
469 config.Save (ConfigurationSaveMode.Minimal);
470 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
473 AssertListElement (nav, label);
478 public void NotModifiedAfterSave ()
480 Run<DefaultMachineConfig> ("NotModifiedAfterSave", (config,label) => {
481 var my = config.Sections ["my"] as MySection;
483 AssertNotModified (my, label);
485 label.EnterScope ("add");
486 var element = my.List.Collection.AddElement ();
487 Assert.That (my.IsModified, Is.True, label.Get ());
488 Assert.That (my.List.IsModified, Is.True, label.Get ());
489 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
490 Assert.That (element.IsModified, Is.False, label.Get ());
493 label.EnterScope ("1st-save");
494 config.Save (ConfigurationSaveMode.Minimal);
495 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
496 config.Save (ConfigurationSaveMode.Modified);
497 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
500 label.EnterScope ("modify");
502 Assert.That (my.IsModified, Is.True, label.Get ());
503 Assert.That (my.List.IsModified, Is.True, label.Get ());
504 Assert.That (my.List.Collection.IsModified, Is.True, label.Get ());
505 Assert.That (element.IsModified, Is.True, label.Get ());
508 label.EnterScope ("2nd-save");
509 config.Save (ConfigurationSaveMode.Modified);
510 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
512 Assert.That (my.IsModified, Is.False, label.Get ());
513 Assert.That (my.List.IsModified, Is.False, label.Get ());
514 Assert.That (my.List.Collection.IsModified, Is.False, label.Get ());
515 Assert.That (element.IsModified, Is.False, label.Get ());
516 label.LeaveScope (); // 2nd-save
521 public void AddSection ()
523 Run ("AddSection", (config,label) => {
524 Assert.That (config.Sections ["my"], Is.Null, label.Get ());
526 var my = new MySection ();
527 config.Sections.Add ("my2", my);
528 config.Save (ConfigurationSaveMode.Full);
530 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
535 public void AddElement ()
537 Run<DefaultMachineConfig> ("AddElement", (config,label) => {
538 var my = config.Sections ["my"] as MySection;
540 AssertNotModified (my, label);
542 var element = my.List.DefaultCollection.AddElement ();
545 config.Save (ConfigurationSaveMode.Modified);
547 label.EnterScope ("file");
548 Assert.That (File.Exists (config.FilePath), Is.True, "#c2");
551 Assert.That (nav.HasChildren, Is.True, label.Get ());
552 var iter = nav.SelectChildren (XPathNodeType.Element);
554 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
555 Assert.That (iter.MoveNext (), Is.True, label.Get ());
557 var my = iter.Current;
558 label.EnterScope ("my");
559 Assert.That (my.Name, Is.EqualTo ("my"), label.Get ());
560 Assert.That (my.HasAttributes, Is.False, label.Get ());
561 Assert.That (my.HasChildren, Is.True, label.Get ());
563 label.EnterScope ("children");
564 var iter2 = my.SelectChildren (XPathNodeType.Element);
565 Assert.That (iter2.Count, Is.EqualTo (1), label.Get ());
566 Assert.That (iter2.MoveNext (), Is.True, label.Get ());
568 var list = iter2.Current;
569 label.EnterScope ("list");
570 Assert.That (list.Name, Is.EqualTo ("list"), label.Get ());
571 Assert.That (list.HasChildren, Is.False, label.Get ());
572 Assert.That (list.HasAttributes, Is.True, label.Get ());
574 var attr = list.GetAttribute ("Hello", string.Empty);
575 Assert.That (attr, Is.EqualTo ("12"), label.Get ());
583 public void ModifyListElement ()
585 Run<RoamingAndExe> ("ModifyListElement", (config,label) => {
586 var my = config.Sections ["my"] as MySection;
588 AssertNotModified (my, label);
592 label.EnterScope ("file");
593 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
595 config.Save (ConfigurationSaveMode.Minimal);
596 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
602 public void ModifyListElement2 ()
604 Run<RoamingAndExe> ("ModifyListElement2", (config,label) => {
605 var my = config.Sections ["my"] as MySection;
607 AssertNotModified (my, label);
611 label.EnterScope ("file");
612 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
614 config.Save (ConfigurationSaveMode.Modified);
615 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
618 AssertListElement (nav, label);
623 public void TestElementWithCollection ()
625 Run<DefaultMachineConfig2> ("TestElementWithCollection", (config,label) => {
626 label.EnterScope ("section");
627 var my2 = config.Sections ["my2"] as MySection2;
628 Assert.That (my2, Is.Not.Null, label.Get ());
630 Assert.That (my2.Test, Is.Not.Null, label.Get ());
631 Assert.That (my2.Test.DefaultCollection, Is.Not.Null, label.Get ());
632 Assert.That (my2.Test.DefaultCollection.Count, Is.EqualTo (0), label.Get ());
635 my2.Test.DefaultCollection.AddElement ();
637 my2.Element.Hello = 29;
639 label.EnterScope ("file");
640 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
642 config.Save (ConfigurationSaveMode.Minimal);
643 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
646 Console.WriteLine (nav.OuterXml);
647 Assert.That (nav.HasChildren, Is.True, label.Get ());
648 var iter = nav.SelectChildren (XPathNodeType.Element);
650 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
651 Assert.That (iter.MoveNext (), Is.True, label.Get ());
653 var my = iter.Current;
654 label.EnterScope ("my2");
655 Assert.That (my.Name, Is.EqualTo ("my2"), label.Get ());
656 Assert.That (my.HasAttributes, Is.False, label.Get ());
657 Assert.That (my.HasChildren, Is.True, label.Get ());
659 label.EnterScope ("children");
660 var iter2 = my.SelectChildren (XPathNodeType.Element);
661 Assert.That (iter2.Count, Is.EqualTo (1), label.Get ());
662 Assert.That (iter2.MoveNext (), Is.True, label.Get ());
664 var element = iter2.Current;
665 label.EnterScope ("element");
666 Assert.That (element.Name, Is.EqualTo ("element"), label.Get ());
667 Assert.That (element.HasChildren, Is.False, label.Get ());
668 Assert.That (element.HasAttributes, Is.True, label.Get ());
670 var attr = element.GetAttribute ("Hello", string.Empty);
671 Assert.That (attr, Is.EqualTo ("29"), label.Get ());
679 public void TestElementWithCollection2 ()
681 Run<DefaultMachineConfig2> ("TestElementWithCollection2", (config,label) => {
682 label.EnterScope ("section");
683 var my2 = config.Sections ["my2"] as MySection2;
684 Assert.That (my2, Is.Not.Null, label.Get ());
686 Assert.That (my2.Test, Is.Not.Null, label.Get ());
687 Assert.That (my2.Test.DefaultCollection, Is.Not.Null, label.Get ());
688 Assert.That (my2.Test.DefaultCollection.Count, Is.EqualTo (0), label.Get ());
691 var element = my2.Test.DefaultCollection.AddElement ();
692 var element2 = element.Test.DefaultCollection.AddElement ();
695 label.EnterScope ("file");
696 Assert.That (File.Exists (config.FilePath), Is.False, label.Get ());
698 config.Save (ConfigurationSaveMode.Minimal);
699 Assert.That (File.Exists (config.FilePath), Is.True, label.Get ());
702 Console.WriteLine (nav.OuterXml);
703 Assert.That (nav.HasChildren, Is.True, label.Get ());
704 var iter = nav.SelectChildren (XPathNodeType.Element);
706 Assert.That (iter.Count, Is.EqualTo (1), label.Get ());
707 Assert.That (iter.MoveNext (), Is.True, label.Get ());
709 var my = iter.Current;
710 label.EnterScope ("my2");
711 Assert.That (my.Name, Is.EqualTo ("my2"), label.Get ());
712 Assert.That (my.HasAttributes, Is.False, label.Get ());
713 Assert.That (my.HasChildren, Is.True, label.Get ());
715 label.EnterScope ("children");
716 var iter2 = my.SelectChildren (XPathNodeType.Element);
717 Assert.That (iter2.Count, Is.EqualTo (1), label.Get ());
718 Assert.That (iter2.MoveNext (), Is.True, label.Get ());
720 var collection = iter2.Current;
721 label.EnterScope ("collection");
722 Assert.That (collection.Name, Is.EqualTo ("collection"), label.Get ());
723 Assert.That (collection.HasChildren, Is.True, label.Get ());
724 Assert.That (collection.HasAttributes, Is.False, label.Get ());
726 label.EnterScope ("children");
727 var iter3 = collection.SelectChildren (XPathNodeType.Element);
728 Assert.That (iter3.Count, Is.EqualTo (1), label.Get ());
729 Assert.That (iter3.MoveNext (), Is.True, label.Get ());
731 var element = iter3.Current;
732 label.EnterScope ("element");
733 Assert.That (element.Name, Is.EqualTo ("test"), label.Get ());
734 Assert.That (element.HasChildren, Is.False, label.Get ());
735 Assert.That (element.HasAttributes, Is.True, label.Get ());
737 var attr = element.GetAttribute ("Hello", string.Empty);
738 Assert.That (attr, Is.EqualTo ("1"), label.Get ());
749 #region Configuration Classes
751 public class MyElement : ConfigurationElement {
752 [ConfigurationProperty ("Hello", DefaultValue = 8)]
754 get { return (int)base ["Hello"]; }
755 set { base ["Hello"] = value; }
758 [ConfigurationProperty ("World", IsRequired = false)]
760 get { return (int)base ["World"]; }
761 set { base ["World"] = value; }
764 new public bool IsModified {
765 get { return base.IsModified (); }
769 public class MyCollection<T> : ConfigurationElementCollection
770 where T : ConfigurationElement, new ()
772 #region implemented abstract members of ConfigurationElementCollection
773 protected override ConfigurationElement CreateNewElement ()
777 protected override object GetElementKey (ConfigurationElement element)
779 return ((T)element).GetHashCode ();
783 public override ConfigurationElementCollectionType CollectionType {
785 return ConfigurationElementCollectionType.BasicMap;
789 public T AddElement ()
791 var element = new T ();
796 public void RemoveElement (T element)
798 BaseRemove (GetElementKey (element));
801 public new bool IsModified {
802 get { return base.IsModified (); }
806 public class MyCollectionElement<T> : ConfigurationElement
807 where T : ConfigurationElement, new ()
809 [ConfigurationProperty ("",
810 Options = ConfigurationPropertyOptions.IsDefaultCollection,
811 IsDefaultCollection = true)]
812 public MyCollection<T> DefaultCollection {
813 get { return (MyCollection<T>)this [String.Empty]; }
814 set { this [String.Empty] = value; }
817 [ConfigurationProperty ("collection", Options = ConfigurationPropertyOptions.None)]
818 public MyCollection<T> Collection {
819 get { return (MyCollection<T>)this ["collection"]; }
820 set { this ["collection"] = value; }
823 public new bool IsModified {
824 get { return base.IsModified (); }
828 public class MySection : ConfigurationSection {
829 [ConfigurationProperty ("list", Options = ConfigurationPropertyOptions.None)]
830 public MyCollectionElement<MyElement> List {
831 get { return (MyCollectionElement<MyElement>) this ["list"]; }
834 [ConfigurationProperty ("test", Options = ConfigurationPropertyOptions.None)]
835 public MyElement Test {
836 get { return (MyElement) this ["test"]; }
839 new public bool IsModified {
840 get { return base.IsModified (); }
845 public class MyElementWithCollection : ConfigurationElement {
846 [ConfigurationProperty ("test")]
847 public MyCollectionElement<MyElement> Test {
848 get { return (MyCollectionElement<MyElement>) this ["test"]; }
852 public class MySection2 : ConfigurationSection {
853 [ConfigurationProperty ("collection", Options = ConfigurationPropertyOptions.None)]
854 public MyCollectionElement<MyElementWithCollection> Test {
855 get { return (MyCollectionElement<MyElementWithCollection>) this ["collection"]; }
858 [ConfigurationProperty ("element", Options = ConfigurationPropertyOptions.None)]
859 public MyElement Element {
860 get { return (MyElement)this ["element"]; }
864 public class MySectionGroup : ConfigurationSectionGroup {
865 public MySection2 My2 {
866 get { return (MySection2)Sections ["my2"]; }