+2010-04-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * System.Xaml_test.dll.sources : add ValueSerializerTest.cs.
+
2010-04-13 Atsushi Enomoto <atsushi@ximian.com>
* System.Xaml_test.dll.sources : add XamlObjectWriterTest.cs.
+2010-04-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ValueSerializer.cs : implement most of them.
+
2010-04-12 Atsushi Enomoto <atsushi@ximian.com>
* TypeExtension.cs, StaticExtension.cs : add [TypeConverter].
{
public static ValueSerializer GetSerializerFor (PropertyDescriptor descriptor)
{
- throw new NotImplementedException ();
+ return GetSerializerFor (descriptor, null);
}
+
public static ValueSerializer GetSerializerFor (Type type)
{
- throw new NotImplementedException ();
+ return GetSerializerFor (type, null);
}
+
public static ValueSerializer GetSerializerFor (PropertyDescriptor descriptor, IValueSerializerContext context)
{
throw new NotImplementedException ();
}
+
+ [MonoTODO ("IValueSerializerContext parameter is not supported")]
public static ValueSerializer GetSerializerFor (Type type, IValueSerializerContext context)
{
- throw new NotImplementedException ();
+ if (type == null)
+ throw new ArgumentNullException ("type");
+
+ // FIXME: it is likely a hack.
+ if (Type.GetTypeCode (type) != TypeCode.Object)
+ return new TypeConverterValueSerializer (type);
+ if (type == typeof (TimeSpan))
+ return new TypeConverterValueSerializer (typeof (TimeSpan));
+ if (type == typeof (Uri))
+ return new TypeConverterValueSerializer (typeof (Uri));
+ return null;
}
+ // instance members
+
public virtual bool CanConvertFromString (string value, IValueSerializerContext context)
{
- throw new NotImplementedException ();
+ return false;
}
+
public virtual bool CanConvertToString (object value, IValueSerializerContext context)
{
- throw new NotImplementedException ();
+ return false;
}
+
public virtual object ConvertFromString (string value, IValueSerializerContext context)
{
- throw new NotImplementedException ();
+ throw new NotSupportedException (String.Format ("Conversion from string '{0}' is not supported", value));
}
+
public virtual string ConvertToString (object value, IValueSerializerContext context)
{
- throw new NotImplementedException ();
+ throw new NotSupportedException (String.Format ("Conversion from '{0}' to string is not supported", value != null ? value.GetType ().Name : "(null)"));
}
protected Exception GetConvertFromException (object value)
throw new NotImplementedException ();
}
}
+
+ internal class StringValueSerializer : ValueSerializer
+ {
+ public override bool CanConvertFromString (string value, IValueSerializerContext context)
+ {
+ return true;
+ }
+
+ public override bool CanConvertToString (object value, IValueSerializerContext context)
+ {
+ return true;
+ }
+
+ public override object ConvertFromString (string value, IValueSerializerContext context)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override string ConvertToString (object value, IValueSerializerContext context)
+ {
+ return (string) value;
+ }
+
+ public override IEnumerable<Type> TypeReferences (object value, IValueSerializerContext context)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ #region Internal implementations.
+
+ internal class TypeConverterValueSerializer<T> : TypeConverterValueSerializer
+ {
+ public TypeConverterValueSerializer ()
+ : base (typeof (T))
+ {
+ }
+ }
+
+ internal class TypeConverterValueSerializer : ValueSerializer
+ {
+ public TypeConverterValueSerializer (Type type)
+ {
+ c = TypeDescriptor.GetConverter (type);
+ }
+
+ TypeConverter c;
+
+ public override bool CanConvertFromString (string value, IValueSerializerContext context)
+ {
+ return c.CanConvertFrom (typeof (string));
+ }
+
+ public override bool CanConvertToString (object value, IValueSerializerContext context)
+ {
+ return c.CanConvertTo (typeof (string));
+ }
+
+ public override object ConvertFromString (string value, IValueSerializerContext context)
+ {
+ return c.ConvertFromInvariantString (value);
+ }
+
+ public override string ConvertToString (object value, IValueSerializerContext context)
+ {
+ return value == null ? String.Empty : c.ConvertToInvariantString (value);
+ }
+
+ public override IEnumerable<Type> TypeReferences (object value, IValueSerializerContext context)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ #endregion
}
+2010-04-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * XamlMember.cs
+ XamlDirective.cs
+ XamlType.cs
+ XamlLanguage.cs : implement (Lookup)ValueSerializer.
+
2010-04-13 Atsushi Enomoto <atsushi@ximian.com>
* XamlXmlWriter.cs :
protected override sealed ICustomAttributeProvider LookupCustomAttributeProvider ()
{
- throw new NotImplementedException ();
+ return null; // as documented.
}
protected override sealed XamlValueConverter<XamlDeferringLoader> LookupDeferringLoader ()
{
- return null;
+ return null; // as documented.
}
protected override sealed IList<XamlMember> LookupDependsOn ()
{
- return base.LookupDependsOn ();
+ return null; // as documented.
}
protected override sealed XamlMemberInvoker LookupInvoker ()
public override string ToString ()
{
- throw new NotImplementedException ();
+ return String.IsNullOrEmpty (PreferredXamlNamespace) ? Name : String.Concat ("{", PreferredXamlNamespace, "}", Name);
}
}
}
public const string Xml1998Namespace = "http://www.w3.org/XML/1998/namespace";
internal const string Xmlns2000Namespace = "http://www.w3.org/2000/xmlns/";
- static readonly XamlSchemaContext sctx = new XamlSchemaContext (null, null);
+ static readonly XamlSchemaContext sctx = new XamlSchemaContext (new Assembly [] {typeof (XamlType).Assembly});
static XamlType XT<T> ()
{
return sctx.GetXamlType (typeof (T));
}
+ internal static readonly bool InitializingDirectives;
+
static XamlLanguage ()
{
// types
// directives
+ // Looks like predefined XamlDirectives have no ValueSerializer.
+ // To handle this situation, differentiate them from non-primitive XamlMembers.
+ InitializingDirectives = true;
+
var nss = new string [] {XamlLanguage.Xaml2006Namespace};
var nssXml = new string [] {XamlLanguage.Xml1998Namespace};
UnknownContent = new XamlDirective (nss, "_UnknownContent", XT<object> (), null, AllowedMemberLocations.MemberElement) { InternalIsUnknown = true };
AllDirectives = new ReadOnlyCollection<XamlDirective> (new XamlDirective [] {Arguments, AsyncRecords, Base, Class, ClassAttributes, ClassModifier, Code, ConnectionId, FactoryMethod, FieldModifier, Initialization, Items, Key, Lang, Members, Name, PositionalParameters, Space, Subclass, SynchronousMode, Shared, TypeArguments, Uid, UnknownContent});
+
+ InitializingDirectives = false;
}
static readonly string [] xaml_nss = new string [] {Xaml2006Namespace};
XamlSchemaContext context;
XamlMemberInvoker invoker;
bool is_attachable, is_event, is_directive;
+ bool is_predefined_directive = XamlLanguage.InitializingDirectives;
string directive_ns;
internal MethodInfo UnderlyingGetter {
public XamlValueConverter<XamlDeferringLoader> DeferringLoader {
get { return LookupDeferringLoader (); }
}
+
+ static readonly XamlMember [] empty_members = new XamlMember [0];
+
public IList<XamlMember> DependsOn {
- get { return LookupDependsOn (); }
+ get { return LookupDependsOn () ?? empty_members; }
}
+
public XamlMemberInvoker Invoker {
get { return LookupInvoker (); }
}
protected virtual ICustomAttributeProvider LookupCustomAttributeProvider ()
{
- throw new NotImplementedException ();
+ return UnderlyingMember;
}
+
protected virtual XamlValueConverter<XamlDeferringLoader> LookupDeferringLoader ()
{
// FIXME: probably fill from attribute.
protected virtual XamlValueConverter<ValueSerializer> LookupValueSerializer ()
{
- // FIXME: probably fill from attribute
- return null;
+ if (is_predefined_directive) // FIXME: this is likely a hack.
+ return null;
+ if (Type == null)
+ return null;
+
+ return XamlType.LookupValueSerializer (Type, LookupCustomAttributeProvider ()) ?? Type.ValueSerializer;
}
void VerifyGetter (MethodInfo method)
return a != null && a.Usable;
}
+ static XamlValueConverter<ValueSerializer> string_value_serializer;
+
protected virtual XamlValueConverter<ValueSerializer> LookupValueSerializer ()
{
- throw new NotImplementedException ();
+ return LookupValueSerializer (this, CustomAttributeProvider);
+ }
+
+ internal static XamlValueConverter<ValueSerializer> LookupValueSerializer (XamlType targetType, ICustomAttributeProvider provider)
+ {
+ if (provider == null)
+ return null;
+
+ var a = provider.GetCustomAttribute<ValueSerializerAttribute> (true);
+ if (a != null)
+ return new XamlValueConverter<ValueSerializer> (a.ValueSerializerType ?? Type.GetType (a.ValueSerializerTypeName), targetType);
+
+ if (targetType.BaseType != null) {
+ var ret = targetType.BaseType.LookupValueSerializer ();
+ if (ret != null)
+ return ret;
+ }
+
+ if (targetType.UnderlyingType == typeof (string)) {
+ if (string_value_serializer == null)
+ string_value_serializer = new XamlValueConverter<ValueSerializer> (typeof (StringValueSerializer), targetType);
+ return string_value_serializer;
+ }
+
+ return null;
}
}
}
System.Windows.Markup/ArrayExtensionTest.cs
System.Windows.Markup/StaticExtensionTest.cs
System.Windows.Markup/TypeExtensionTest.cs
+System.Windows.Markup/ValueSerializerTest.cs
System.Xaml.Schema/XamlMemberInvokerTest.cs
System.Xaml.Schema/XamlTypeInvokerTest.cs
System.Xaml.Schema/XamlTypeTypeConverterTest.cs
+2010-04-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * ValueSerializerTest.cs : new test.
+
2010-04-09 Atsushi Enomoto <atsushi@ximian.com>
* ArrayExtensionTest.cs
--- /dev/null
+//
+// Copyright (C) 2010 Novell Inc. http://novell.com
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Windows.Markup;
+using System.Xaml;
+using System.Xaml.Schema;
+using NUnit.Framework;
+
+using Category = NUnit.Framework.CategoryAttribute;
+
+namespace MonoTests.System.Windows.Markup
+{
+ [TestFixture]
+ public class ValueSerializerTest
+ {
+ static ValueSerializerTest ()
+ {
+ std_types = new List<XamlType> (XamlLanguage.AllTypes);
+ std_types.Sort ((t1, t2) => String.CompareOrdinal (t1.Name, t2.Name));
+ }
+
+ static readonly List<XamlType> std_types;
+ object [] test_values = {null, true, "test", 3, 'x', 5.5, -1.414m, (byte) 255, new Uri ("urn:foo"), new NullExtension (), new object (), new PropertyDefinition (), new Reference ("Foo"), new StaticExtension (), TimeSpan.FromMinutes (5), new TypeExtension ("TypeExt"), new XData () { Text = "test xdata"} }; // can we instantiate MemberDefinition?
+ string [] test_strings = {String.Empty, "True", "test", "3", "x", "5.5", "-1.414", "255", "urn:foo", "System.Windows.Markup.NullExtension", "System.Object", "System.Windows.Markup.PropertyDefinition", "System.Windows.Markup.Reference", "System.Windows.Markup.StaticExtension", "00:05:00", "System.Windows.Markup.TypeExtension", "System.Windows.Markup.XData"};
+
+ [Test]
+ public void SerializerInAllTypes ()
+ {
+ var sctx = new XamlSchemaContext (new Assembly [] { typeof (XamlType).Assembly });
+ foreach (var t in std_types) {
+ if (t != XamlLanguage.String) {
+ Assert.IsNull (t.ValueSerializer, "IsNull? " + t.Name);
+ continue;
+ }
+ var v = t.ValueSerializer.ConverterInstance;
+ foreach (var val in test_values)
+ Assert.IsTrue (v.CanConvertToString (val, null), t.Name + "_" + (val != null ? val.GetType () : null));
+ }
+ }
+
+ static readonly Type [] no_ser_types = {typeof (object), typeof (ArrayExtension), typeof (MemberDefinition), typeof (NullExtension), typeof (PropertyDefinition), typeof (Reference), typeof (StaticExtension), typeof (TypeExtension), typeof (XData)};
+
+ [Test]
+ public void GetSerializerForAllTypes ()
+ {
+ // Serializers from GetSerializerFor() returns very
+ // different results from predefined ValueSerializer.
+ foreach (var t in std_types) {
+ var v = ValueSerializer.GetSerializerFor (t.UnderlyingType, null);
+ if (no_ser_types.Any (ti => ti == t.UnderlyingType)) {
+ Assert.IsNull (v, "NoSerializer_" + t.Name);
+ continue;
+ }
+
+ // String ValueSerializer is the only exceptional one that mostly fails ConvertToString().
+ // For remaining types, ConvertToString() should succeed.
+ // What is funny or annoying here is, that always return true for CanConvertToString() while everything fails at ConvertToString() on .NET.
+ if (t.UnderlyingType == typeof (string))
+ continue;
+
+ int i = 0;
+ foreach (var val in test_values) {
+ Assert.IsTrue (v.CanConvertToString (val, null), t.Name + "_" + (val != null ? val.GetType () : null));
+ Assert.AreEqual (test_strings [i++], v.ConvertToString (val, null), "value-" + t.Name + "_" + val);
+ }
+
+ // The funny thing also applies to CanConvertToString() and ConvertToString().
+
+ i = 0;
+ foreach (var str in test_strings) {
+ Assert.IsTrue (v.CanConvertFromString (str, null), t.Name + "_" + str);
+ // FIXME: add tests for this large matrix someday.
+ //Assert.AreEqual (test_values [i++], v.ConvertFromString (str, null), "value-" + t.Name + "_" + str);
+ }
+ }
+ }
+
+ [Test]
+ public void DefaultImplementation ()
+ {
+ var v = new MyValueSerializer ();
+
+ int i = 0;
+ foreach (var val in test_values) {
+ Assert.IsFalse (v.CanConvertToString (val, null), "CanConvertTo." + val);
+ try {
+ v.ConvertToString (val, null);
+ Assert.Fail ("ConvertTo." + val);
+ } catch (NotSupportedException) {
+ }
+ }
+
+ // The funny thing also applies to CanConvertToString() and ConvertToString().
+
+ i = 0;
+ foreach (var str in test_strings) {
+ Assert.IsFalse (v.CanConvertFromString (str, null), "CanConvertFrom." + str);
+ try {
+ v.ConvertFromString (str, null);
+ Assert.Fail ("ConvertFrom." + str);
+ } catch (NotSupportedException) {
+ }
+ }
+ }
+
+ class MyValueSerializer : ValueSerializer
+ {
+ }
+ }
+}
+2010-04-14 Atsushi Enomoto <atsushi@ximian.com>
+
+ * XamlTypeTest.cs, XamlLanguageTest.cs : enable ValueSerializer tests.
+
2010-04-13 Atsushi Enomoto <atsushi@ximian.com>
* XamlXmlWriterTest.cs : enable WriteNode() tests.
{
var t = XamlLanguage.String;
TestXamlTypePrimitive (t, "String", typeof (string), true, true);
+ Assert.IsNotNull (XamlLanguage.AllTypes.First (tt => tt.Name == "String").ValueSerializer, "#x");
+ Assert.IsNotNull (XamlLanguage.String.ValueSerializer, "#y");
/* Those properties are pointless regarding practical use. Those "members" does not participate in serialization.
var l = t.GetAllAttachableMembers ().ToArray ();
Assert.IsFalse (t.IsAmbient, "#22");
//Assert.IsNull (t.AllowedContentTypes, "#23");
//Assert.IsNull (t.ContentWrappers, "#24");
- //Assert.IsNull (t.ValueSerializer, "#26");
+ // string is a special case.
+ if (t == XamlLanguage.String)
+ Assert.IsNotNull (t.ValueSerializer, "#26");
+ else
+ Assert.IsNull (t.ValueSerializer, "#26");
//Assert.IsNull (t.DeferringLoader, "#28");
}
}
void TestMemberCommon (XamlMember m, string name, Type type, Type declType, bool hasSetter)
- {
- TestMemberCommon (m, name, type, declType, hasSetter, type == typeof (string));
- }
-
- void TestMemberCommon (XamlMember m, string name, Type type, Type declType, bool hasSetter, bool hasSerializer)
{
Assert.IsNotNull (m, "#1");
Assert.IsNotNull (m.DeclaringType, "#2");
Assert.AreEqual (new XamlType (declType, m.TargetType.SchemaContext), m.TargetType, "#10");
Assert.IsNotNull (m.Type, "#11");
Assert.AreEqual (type, m.Type.UnderlyingType, "#11-2");
- // FIXME: test TypeConverter and ValueSerializer
-// Assert.IsNull (m.TypeConverter, "#12");
-// Assert.AreEqual (hasSerializer, m.ValueSerializer != null, "#13");
+ // Property.Type is a special case here.
+ if (name == "Type" && m.DeclaringType != XamlLanguage.Property)
+ Assert.AreEqual (m.Type.TypeConverter, m.TypeConverter, "#12");
+ // String type is a special case here.
+ if (type == typeof (string))
+ Assert.AreEqual (m.Type.ValueSerializer, m.ValueSerializer, "#13a");
+ else
+ Assert.IsNull (m.ValueSerializer, "#13b");
Assert.IsNull (m.DeferringLoader, "#14");
Assert.IsNotNull (m.UnderlyingMember, "#15");
Assert.AreEqual (!hasSetter, m.IsReadOnly, "#16");
namespace MonoTests.System.Xaml
{
- // FIXME: enable AllowedContentTypes, ContentWrappers, DeferringLoader and ValueSerializer tests.
+ // FIXME: enable AllowedContentTypes, ContentWrappers and DeferringLoader tests.
[TestFixture]
public class XamlTypeTest
{
}
[Test]
- [Ignore ("It results in NRE on .NET 4.0 RC")]
+ [Ignore ("It results in NRE on .NET 4.0 RTM")]
public void EmptyTypeArguments ()
{
var t1 = new MyXamlType ("System.Int32", null, sctx);
//Assert.IsNull (t.ContentWrappers, "#24");
Assert.IsNotNull (t.TypeConverter, "#25");
Assert.IsTrue (t.TypeConverter.ConverterInstance is Int32Converter, "#25-2");
- //Assert.IsNull (t.ValueSerializer, "#26");
+ Assert.IsNull (t.ValueSerializer, "#26");
Assert.IsNull (t.ContentProperty, "#27");
//Assert.IsNull (t.DeferringLoader, "#28");
Assert.IsNull (t.MarkupExtensionReturnType, "#29");
//Assert.IsNull (t.AllowedContentTypes, "#23");
//Assert.IsNull (t.ContentWrappers, "#24");
Assert.IsNull (t.TypeConverter, "#25");
- //Assert.IsNull (t.ValueSerializer, "#26");
+ Assert.IsNull (t.ValueSerializer, "#26");
Assert.IsNull (t.ContentProperty, "#27");
//Assert.IsNull (t.DeferringLoader, "#28");
Assert.IsNull (t.MarkupExtensionReturnType, "#29");
//Assert.IsNull (t.AllowedContentTypes, "#23");
//Assert.IsNull (t.ContentWrappers, "#24");
Assert.IsNull (t.TypeConverter, "#25");
- //Assert.IsNull (t.ValueSerializer, "#26");
+ Assert.IsNull (t.ValueSerializer, "#26");
Assert.IsNull (t.ContentProperty, "#27");
//Assert.IsNull (t.DeferringLoader, "#28");
Assert.IsNull (t.MarkupExtensionReturnType, "#29");
// Assert.IsNull (t.AllowedContentTypes, "#23");
// Assert.IsNull (t.ContentWrappers, "#24");
Assert.IsNull (t.TypeConverter, "#25");
- // Assert.IsNull (t.ValueSerializer, "#26");
+ Assert.IsNull (t.ValueSerializer, "#26");
Assert.IsNotNull (t.ContentProperty, "#27");
Assert.AreEqual ("Name", t.ContentProperty.Name, "#27-2");
// Assert.IsNull (t.DeferringLoader, "#28");