2 // Copyright (C) 2010 Novell Inc. http://novell.com
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 using System.Collections;
25 using System.Collections.Generic;
26 using System.ComponentModel;
27 using System.Diagnostics;
28 using System.Globalization;
31 using System.Reflection;
32 using System.Windows.Markup;
34 using System.Xaml.Schema;
36 using System.Xml.Schema;
37 using System.Xml.Serialization;
39 [assembly: XmlnsDefinition ("http://www.domain.com/path", "XamlTest")] // bug #680385
40 [assembly: XmlnsDefinition ("http://www.domain.com/path", "SecondTest")] // bug #681045, same xmlns key for different clrns.
42 namespace MonoTests.System.Xaml
44 public class ArgumentAttributed
46 public ArgumentAttributed (string s1, string s2)
52 [ConstructorArgument ("s1")]
53 public string Arg1 { get; set; }
55 [ConstructorArgument ("s2")]
56 public string Arg2 { get; set; }
59 public class ComplexPositionalParameterWrapper
61 public ComplexPositionalParameterWrapper ()
65 public ComplexPositionalParameterClass Param { get; set; }
68 [TypeConverter (typeof (ComplexPositionalParameterClassConverter))]
69 public class ComplexPositionalParameterClass : MarkupExtension
71 public ComplexPositionalParameterClass (ComplexPositionalParameterValue value)
76 [ConstructorArgument ("value")]
77 public ComplexPositionalParameterValue Value { get; private set; }
79 public override object ProvideValue (IServiceProvider sp)
85 public class ComplexPositionalParameterClassConverter : TypeConverter
87 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
89 return sourceType == typeof (string);
92 public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object valueToConvert)
94 return new ComplexPositionalParameterClass (new ComplexPositionalParameterValue () {Foo = (string) valueToConvert});
97 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
99 // conversion to string is not supported.
100 return destinationType == typeof (ComplexPositionalParameterClass);
104 public class ComplexPositionalParameterValue
106 public string Foo { get; set; }
109 //[MarkupExtensionReturnType (typeof (Array))]
110 //[ContentProperty ("Items")] ... so, these attributes do not affect XamlObjectReader.
111 public class MyArrayExtension : MarkupExtension
113 public MyArrayExtension ()
115 items = new ArrayList ();
118 public MyArrayExtension (Array array)
120 items = new ArrayList (array);
121 this.Type = array.GetType ().GetElementType ();
124 public MyArrayExtension (Type type)
132 get { return items; }
133 private set { items = value; }
136 [ConstructorArgument ("type")]
137 public Type Type { get; set; }
139 public override object ProvideValue (IServiceProvider serviceProvider)
142 throw new InvalidOperationException ("Type property must be set before calling ProvideValue method");
144 Array a = Array.CreateInstance (Type, Items.Count);
150 // The trailing "A" gives significant difference in XML output!
151 public class MyArrayExtensionA : MarkupExtension
153 public MyArrayExtensionA ()
155 items = new ArrayList ();
158 public MyArrayExtensionA (Array array)
160 items = new ArrayList (array);
161 this.Type = array.GetType ().GetElementType ();
164 public MyArrayExtensionA (Type type)
172 get { return items; }
173 private set { items = value; }
176 [ConstructorArgument ("type")]
177 public Type Type { get; set; }
179 public override object ProvideValue (IServiceProvider serviceProvider)
182 throw new InvalidOperationException ("Type property must be set before calling ProvideValue method");
184 Array a = Array.CreateInstance (Type, Items.Count);
194 public class TestClass3
196 public TestClass3 Nested { get; set; }
199 public class TestClass4
201 public string Foo { get; set; }
202 public string Bar { get; set; }
205 public class TestClass5
207 public static string Foo { get; set; }
208 public string Bar { get; set; }
209 public string Baz { internal get; set; }
210 public string ReadOnly {
215 public class MyExtension : MarkupExtension
217 public MyExtension ()
221 public MyExtension (Type arg1, string arg2, string arg3)
228 [ConstructorArgument ("arg1")]
229 public Type Foo { get; set; }
231 [ConstructorArgument ("arg2")]
232 public string Bar { get; set; }
234 [ConstructorArgument ("arg3")]
235 public string Baz { get; set; }
237 public override object ProvideValue (IServiceProvider provider)
239 return "provided_value";
243 [TypeConverter (typeof (StringConverter))] // This attribute is the markable difference between MyExtension and this type.
244 public class MyExtension2 : MarkupExtension
246 public MyExtension2 ()
250 public MyExtension2 (Type arg1, string arg2)
256 [ConstructorArgument ("arg1")]
257 public Type Foo { get; set; }
259 [ConstructorArgument ("arg2")]
260 public string Bar { get; set; }
262 public override object ProvideValue (IServiceProvider provider)
264 return "provided_value";
268 [TypeConverter (typeof (StringConverter))] // same as MyExtension2 except that it is *not* MarkupExtension.
269 public class MyExtension3
271 public MyExtension3 ()
275 // cf. According to [MS-XAML-2009] 3.2.1.11, constructors are invalid unless the type is derived from TypeExtension. So, it is likely *ignored*.
276 public MyExtension3 (Type arg1, string arg2)
282 [ConstructorArgument ("arg1")]
283 public Type Foo { get; set; }
285 [ConstructorArgument ("arg2")]
286 public string Bar { get; set; }
289 [TypeConverter (typeof (DateTimeConverter))] // same as MyExtension3 except for the type converter.
290 public class MyExtension4
292 public MyExtension4 ()
296 // cf. According to [MS-XAML-2009] 3.2.1.11, constructors are invalid unless the type is derived from TypeExtension. So, it is likely *ignored*.
297 public MyExtension4 (Type arg1, string arg2)
303 [ConstructorArgument ("arg1")]
304 public Type Foo { get; set; }
306 [ConstructorArgument ("arg2")]
307 public string Bar { get; set; }
310 // no type converter, and there are only simple-type arguments == _PositionalParameters is applicable.
311 public class MyExtension5 : MarkupExtension
313 public MyExtension5 (string arg1, string arg2)
319 [ConstructorArgument ("arg1")]
320 public string Foo { get; set; }
322 [ConstructorArgument ("arg2")]
323 public string Bar { get; set; }
325 public override object ProvideValue (IServiceProvider sp)
331 // Almost the same as MyExtension5, BUT there is default constructor which XamlObjectReader prefers.
332 public class MyExtension6 : MarkupExtension
334 public MyExtension6 ()
338 public MyExtension6 (string arg1)
343 [ConstructorArgument ("arg1")]
344 public string Foo { get; set; }
346 public override object ProvideValue (IServiceProvider sp)
352 public class PositionalParametersClass1 : MarkupExtension
354 public PositionalParametersClass1 (string foo)
359 public PositionalParametersClass1 (string foo, int bar)
365 [ConstructorArgument ("foo")]
366 public string Foo { get; set; }
368 [ConstructorArgument ("bar")]
369 public int Bar { get; set; }
371 public override object ProvideValue (IServiceProvider sp)
377 public class PositionalParametersWrapper
379 public PositionalParametersClass1 Body { get; set; }
381 public PositionalParametersWrapper ()
385 public PositionalParametersWrapper (string foo, int bar)
387 Body = new PositionalParametersClass1 (foo, bar);
391 public class ListWrapper
393 public ListWrapper ()
395 Items = new List<int> ();
398 public ListWrapper (List<int> items)
403 public List<int> Items { get; private set; }
406 public class ListWrapper2
408 public ListWrapper2 ()
410 Items = new List<int> ();
413 public ListWrapper2 (List<int> items)
418 public List<int> Items { get; set; } // it is settable, which makes difference.
421 [ContentProperty ("Content")]
422 public class ContentIncludedClass
424 public string Content { get; set; }
427 public class StaticClass1
429 static StaticClass1 ()
434 public static string FooBar { get; set; }
437 public class StaticExtensionWrapper
439 public StaticExtensionWrapper ()
443 public StaticExtension Param { get; set; }
445 public static string Foo = "foo";
448 public class TypeExtensionWrapper
450 public TypeExtensionWrapper ()
454 public TypeExtension Param { get; set; }
457 public class XDataWrapper
459 public XData Markup { get; set; }
462 // FIXME: test it with XamlXmlReader (needs to create xml first)
463 public class EventContainer
465 public event Action Run;
468 public class NamedItem
472 References = new List<NamedItem> ();
475 public NamedItem (string name)
481 public string ItemName { get; set; }
482 public IList<NamedItem> References { get; private set; }
485 [RuntimeNameProperty ("ItemName")]
486 public class NamedItem2
490 References = new List<NamedItem2> ();
493 public NamedItem2 (string name)
499 public string ItemName { get; set; }
500 public IList<NamedItem2> References { get; private set; }
503 [TypeConverter (typeof (TestValueConverter))]
504 public class TestValueSerialized
506 public TestValueSerialized ()
510 public string Foo { get; set; }
513 public class TestValueConverter : TypeConverter
515 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
517 //Console.Error.WriteLine ("### {0}:{1}", sourceType, context);
518 ValueSerializerContextTest.Context = (IValueSerializerContext) context;
522 public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object source)
524 //Console.Error.WriteLine ("##### {0}:{1}", source, context);
525 ValueSerializerContextTest.Provider = (IServiceProvider) context;
526 var sp = context as IServiceProvider;
527 // ValueSerializerContextTest.Context = (IValueSerializerContext) context; -> causes InvalidCastException
528 if ((source as string) == "v")
529 return new TestValueSerialized ();
530 throw new Exception ("huh");
533 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
535 //Console.Error.WriteLine ("$$$ {0}:{1}", destinationType, context);
536 ValueSerializerContextTest.Context = (IValueSerializerContext) context;
537 return destinationType != typeof (MarkupExtension);
541 [ContentProperty ("Value")]
542 public class XmlSerializableWrapper
544 public XmlSerializableWrapper () // mandatory
545 : this (new XmlSerializable ())
549 public XmlSerializableWrapper (XmlSerializable val)
556 public XmlSerializable Value {
558 // To make it become XData, it cannot have a setter.
562 public class XmlSerializable : IXmlSerializable
564 public XmlSerializable ()
568 public XmlSerializable (string raw)
575 public string GetRaw ()
580 public void ReadXml (XmlReader reader)
582 reader.MoveToContent ();
583 raw = reader.ReadOuterXml ();
586 public void WriteXml (XmlWriter writer)
589 var xr = XmlReader.Create (new StringReader (raw));
591 writer.WriteNode (xr, false);
595 public XmlSchema GetSchema ()
601 public class Attachable
603 public static readonly AttachableMemberIdentifier FooIdentifier = new AttachableMemberIdentifier (typeof (Attachable), "Foo");
604 public static readonly AttachableMemberIdentifier ProtectedIdentifier = new AttachableMemberIdentifier (typeof (Attachable), "Protected");
606 public static string GetFoo (object target)
609 return AttachablePropertyServices.TryGetProperty (target, FooIdentifier, out v) ? v : null;
612 public static void SetFoo (object target, string value)
614 AttachablePropertyServices.SetProperty (target, FooIdentifier, value);
617 public static string GetBar (object target, object signatureMismatch)
622 public static void SetBar (object signatureMismatch)
626 public static void GetBaz (object noReturnType)
630 public static string SetBaz (object target, object extraReturnType)
635 protected static string GetProtected (object target)
638 return AttachablePropertyServices.TryGetProperty (target, ProtectedIdentifier, out v) ? v : null;
641 protected static void SetProtected (object target, string value)
643 AttachablePropertyServices.SetProperty (target, ProtectedIdentifier, value);
646 static Dictionary<object,List<EventHandler>> handlers = new Dictionary<object,List<EventHandler>> ();
648 public static void AddXHandler (object target, EventHandler handler)
650 List<EventHandler> l;
651 if (!handlers.TryGetValue (target, out l)) {
652 l = new List<EventHandler> ();
653 handlers [target] = l;
658 public static void RemoveXHandler (object target, EventHandler handler)
660 handlers [target].Remove (handler);
664 public class AttachedPropertyStore : IAttachedPropertyStore
666 public AttachedPropertyStore ()
670 Dictionary<AttachableMemberIdentifier,object> props = new Dictionary<AttachableMemberIdentifier,object> ();
672 public int PropertyCount {
673 get { return props.Count; }
676 public void CopyPropertiesTo (KeyValuePair<AttachableMemberIdentifier, object> [] array, int index)
678 ((ICollection<KeyValuePair<AttachableMemberIdentifier, object>>) props).CopyTo (array, index);
681 public bool RemoveProperty (AttachableMemberIdentifier attachableMemberIdentifier)
683 return props.Remove (attachableMemberIdentifier);
686 public void SetProperty (AttachableMemberIdentifier attachableMemberIdentifier, object value)
688 props [attachableMemberIdentifier] = value;
691 public bool TryGetProperty (AttachableMemberIdentifier attachableMemberIdentifier, out object value)
693 return props.TryGetValue (attachableMemberIdentifier, out value);
697 public class AttachedWrapper : AttachedPropertyStore
699 public AttachedWrapper ()
701 Value = new Attached ();
704 public Attached Value { get; set; }
707 public class AttachedWrapper2
709 public static readonly AttachableMemberIdentifier FooIdentifier = new AttachableMemberIdentifier (typeof (AttachedWrapper2), "Foo");
711 static AttachedPropertyStore store = new AttachedPropertyStore ();
713 public static string GetFoo (object target)
716 return store.TryGetProperty (FooIdentifier, out v) ? (string) v : null;
719 public static void SetFoo (object target, string value)
721 store.SetProperty (FooIdentifier, value);
724 public static int PropertyCount {
725 get { return store.PropertyCount; }
728 public AttachedWrapper2 ()
730 Value = new Attached ();
733 public Attached Value { get; set; }
736 public class Attached : Attachable
740 public class Attached2
742 internal String Property { get; set; }
745 public class AttachedWrapper3
747 public static void SetProperty (Attached2 a, string value)
753 public class EventStore
755 public bool Method1Invoked;
757 public event EventHandler<EventArgs> Event1;
758 public event Func<object> Event2;
760 public object Examine ()
763 Event1 (this, EventArgs.Empty);
770 public void Method1 ()
772 throw new Exception ();
775 public void Method1 (object o, EventArgs e)
777 Method1Invoked = true;
780 public object Method2 ()
786 public class EventStore2<TEventArgs> where TEventArgs : EventArgs
788 public bool Method1Invoked;
790 public event EventHandler<TEventArgs> Event1;
791 public event Func<object> Event2;
793 public object Examine ()
796 Event1 (this, default (TEventArgs));
803 public void Method1 ()
805 throw new Exception ();
808 public void Method1 (object o, EventArgs e)
810 throw new Exception ();
813 public void Method1 (object o, TEventArgs e)
815 Method1Invoked = true;
818 public object Method2 ()
824 public class AbstractContainer
826 public AbstractObject Value1 { get; set; }
827 public AbstractObject Value2 { get; set; }
830 public abstract class AbstractObject
832 public abstract string Foo { get; set; }
835 public class DerivedObject : AbstractObject
837 public override string Foo { get; set; }
840 public class ReadOnlyPropertyContainer
845 set { foo = Bar = value; }
847 public string Bar { get; private set; }
850 public class EnumContainer
852 public EnumValueType EnumProperty { get; set; }
855 public enum EnumValueType
863 [ContentProperty ("ListOfItems")]
864 public class CollectionContentProperty
866 public IList<SimpleClass> ListOfItems { get; set; }
868 public CollectionContentProperty ()
870 this.ListOfItems = new List<SimpleClass> ();
874 [ContentProperty ("ListOfItems")]
875 public class CollectionContentPropertyX
877 public IList ListOfItems { get; set; }
879 public CollectionContentPropertyX ()
881 this.ListOfItems = new List<IEnumerable> ();
885 public class SimpleClass
889 public class NullableContainer
891 public int? TestProp { get; set; }
894 public class DirectListContainer // for such xml that directly contains items in <*.Items> element.
896 public IList<DirectListContent> Items { get; set; }
898 public DirectListContainer ()
900 this.Items = new List<DirectListContent> ();
904 public class DirectListContent
906 public string Value { get; set; }
909 public class DirectDictionaryContainer // for such xml that directly contains items in <*.Items> element.
911 public IDictionary<EnumValueType,int> Items { get; set; }
913 public DirectDictionaryContainer ()
915 this.Items = new Dictionary<EnumValueType,int> ();
922 public class Configurations : List<Configuration>
924 private Configuration active;
925 private bool isFrozen;
927 public Configuration Active {
928 get { return this.active; }
931 throw new InvalidOperationException ("The 'Active' configuration can only be changed via modifying the source file (" + this.Source + ").");
938 public string Source { get; private set; }
941 public class Configuration
943 public string Version { get; set; }
945 public string Path { get; set; }
952 public class TypeOtherAssembly
954 [TypeConverter (typeof (NullableUintListConverter))]
955 public List<uint?> Values { get; set; }
957 public TypeOtherAssembly ()
959 this.Values = new List<uint?> ();
963 public class NullableUintListConverter : CustomTypeConverterBase
965 public override object ConvertFrom (System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
967 string configValue = value as string;
968 if (string.IsNullOrWhiteSpace (configValue))
971 string delimiterStr = ", ";
972 char [] delimiters = delimiterStr.ToCharArray ();
973 string [] tokens = configValue.Split (delimiters, StringSplitOptions.RemoveEmptyEntries);
975 List<uint?> parsedList = new List<uint?> (tokens.Length);
976 foreach (string token in tokens)
977 parsedList.Add(uint.Parse(token));
982 public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
984 var v = (List<uint?>) value;
985 return String.Join (", ", (from i in v select i.ToString ()).ToArray ());
989 public class CustomTypeConverterBase : TypeConverter
991 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
993 if (sourceType == typeof (string))
997 return base.CanConvertFrom (context, sourceType);
1003 [MarkupExtensionReturnType (typeof (object))]
1004 public class ResourceExtension : MarkupExtension
1006 [ConstructorArgument ("key")]
1007 public object Key { get; set; }
1009 public ResourceExtension (object key)
1014 public override object ProvideValue (IServiceProvider serviceProvider)
1016 IXamlSchemaContextProvider service = serviceProvider.GetService (typeof (IXamlSchemaContextProvider)) as IXamlSchemaContextProvider;
1017 IAmbientProvider provider = serviceProvider.GetService (typeof (IAmbientProvider)) as IAmbientProvider;
1018 Debug.Assert (provider != null, "The provider should not be null!");
1020 XamlSchemaContext schemaContext = service.SchemaContext;
1021 XamlType[] types = new XamlType [] { schemaContext.GetXamlType (typeof (ResourcesDict)) };
1023 // ResourceDict is marked as Ambient, so the instance current being deserialized should be in this list.
1024 List<AmbientPropertyValue> list = provider.GetAllAmbientValues (null, false, types) as List<AmbientPropertyValue>;
1025 if (list.Count != 1)
1026 throw new Exception ("expected ambient property count == 1 but " + list.Count);
1027 for (int i = 0; i < list.Count; i++) {
1028 AmbientPropertyValue value = list [i];
1029 ResourcesDict dict = value.Value as ResourcesDict;
1031 // For this example, we know that dict should not be null and that it is the only value in list.
1032 object result = dict [this.Key];
1040 [UsableDuringInitialization (true), Ambient]
1041 public class ResourcesDict : Dictionary<object, object>
1045 public class TestObject
1047 public TestObject TestProperty { get; set; }
1052 public class ResourcesDict2 : Dictionary<object, object>
1056 public class TestObject2
1058 public string TestProperty { get; set; }
1062 [ContentProperty ("Items")]
1063 public class SimpleType
1065 public IList<SimpleType> Items { get; set; }
1067 public IList<SimpleType> NonContentItems { get; set; }
1069 public string TestProperty { get; set; }
1071 public SimpleType ()
1073 this.Items = new List<SimpleType> ();
1074 this.NonContentItems=new List<SimpleType> ();
1078 public class ContentPropertyContainer : Dictionary<object, object>