提交 b0ffa90c 编写于 作者: A Atsushi Eno

Significant XamlObjectWriter rewrite for solid state transition. And now it...

Significant XamlObjectWriter rewrite for solid state transition. And now it supports Array(Extension) and other MarkupExtension types.
上级 38e92f5c
......@@ -58,6 +58,7 @@ namespace System.Windows.Markup
Items = new List<object> ();
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
public IList Items { get; private set; }
[ConstructorArgument ("arrayType")]
......
......@@ -51,10 +51,13 @@ namespace System.Windows.Markup
throw new ArgumentNullException ("serviceProvider");
if (Name == null)
throw new InvalidOperationException ("Name property is not set");
var r = ((object) serviceProvider) as IXamlNameResolver;
var r = serviceProvider.GetService (typeof (IXamlNameResolver)) as IXamlNameResolver;
if (r == null)
throw new ArgumentException ("serviceProvider does not implement IXamlNameResolver");
return r.Resolve (Name);
throw new InvalidOperationException ("serviceProvider does not implement IXamlNameResolver");
var ret = r.Resolve (Name);
if (ret == null)
ret = r.GetFixupToken (new string [] {Name}, true);
return ret;
}
}
}
......@@ -54,6 +54,7 @@ namespace System.Windows.Markup
[ConstructorArgument ("type")]
[DefaultValue (null)]
public Type Type { get; set; }
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public string TypeName { get; set; }
public override object ProvideValue (IServiceProvider serviceProvider)
......
......@@ -34,7 +34,12 @@ namespace System.Windows.Markup
{
public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
{
return false;
// unlike implied at http://msdn.microsoft.com/en-us/library/ee621338.aspx , it does not support IXamlTypeResolver.
//if (sourceType == typeof (string) && context != null) {
// var xtr = context.GetService (typeof (IXamlTypeResolver)) as IXamlTypeResolver;
// return xtr != null;
//}
return base.CanConvertFrom (context, sourceType);
}
public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
......@@ -44,7 +49,7 @@ namespace System.Windows.Markup
public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
{
throw new NotSupportedException (String.Format ("Conversion from type {0} is not supported", value != null ? value.GetType () : null));
return base.ConvertFrom (context, culture, value);
}
public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
......
......@@ -50,7 +50,7 @@ namespace System.Xaml.Schema
void ThrowIfUnknown ()
{
if (type.UnderlyingType == null)
throw new InvalidOperationException (String.Format ("Current operation is valid only when the underlying type on a XamlType is known, but it is unknown for '{0}'", type));
throw new NotSupportedException (String.Format ("Current operation is valid only when the underlying type on a XamlType is known, but it is unknown for '{0}'", type));
}
public EventHandler<XamlSetMarkupExtensionEventArgs> SetMarkupExtensionHandler {
......@@ -67,6 +67,11 @@ namespace System.Xaml.Schema
throw new ArgumentNullException ("instance");
var t = instance.GetType ();
if (type.UnderlyingType != null) {
if (!type.SchemaContext.GetXamlType (t).IsCollection) // not sure why this check is done only when UnderlyingType exists...
throw new NotSupportedException (String.Format ("Non-collection type '{0}' does not support this operation", t));
}
MethodInfo mi;
if (t.IsGenericType)
mi = instance.GetType ().GetMethod ("Add", t.GetGenericArguments ());
......
......@@ -23,6 +23,7 @@
using System;
using System.Collections.Generic;
using System.Windows.Markup;
using System.Xaml.Schema;
namespace System.Xaml
{
......@@ -39,6 +40,8 @@ namespace System.Xaml
throw new ArgumentNullException ("schemaContext");
this.sctx = schemaContext;
this.settings = settings ?? new XamlObjectWriterSettings ();
service_provider = new XamlObjectWriterServiceProvider (this);
}
XamlSchemaContext sctx;
......@@ -47,17 +50,24 @@ namespace System.Xaml
XamlWriterStateManager manager = new XamlWriterStateManager<XamlObjectWriterException, XamlObjectWriterException> (false);
object result;
int line = -1, column = -1;
Stack<object> objects = new Stack<object> ();
Stack<XamlType> types = new Stack<XamlType> ();
Stack<XamlMember> members = new Stack<XamlMember> ();
List<object> arguments = new List<object> (); // FIXME: so far it has no contents.
string factory_method;
bool object_instantiated;
Stack<List<object>> contents_stack = new Stack<List<object>> ();
List<object> objects_from_getter = new List<object> ();
Stack<List<XamlMember>> written_properties_stack = new Stack<List<XamlMember>> ();
XamlNameResolver name_resolver = new XamlNameResolver ();
List<NamespaceDeclaration> namespaces = new List<NamespaceDeclaration> ();
IServiceProvider service_provider;
Stack<ObjectState> object_states = new Stack<ObjectState> ();
class ObjectState
{
public XamlType Type;
public object Value;
public List<object> Contents = new List<object> ();
public List<XamlMember> WrittenProperties = new List<XamlMember> ();
public bool IsInstantiated;
public bool IsGetObject;
public string FactoryMethod;
public List<object> Arguments = new List<object> ();
}
public virtual object Result {
get { return result; }
......@@ -85,9 +95,9 @@ namespace System.Xaml
if (!disposing)
return;
while (types.Count > 0) {
while (object_states.Count > 0) {
WriteEndObject ();
if (types.Count > 0)
if (object_states.Count > 0)
WriteEndMember ();
}
}
......@@ -126,7 +136,7 @@ namespace System.Xaml
if (member.IsDirective)
return;
if (!OnSetValue (this, member, value))
member.Invoker.SetValue (objects.Peek (), value);
member.Invoker.SetValue (object_states.Peek ().Value, value);
}
public void SetLineInfo (int lineNumber, int linePosition)
......@@ -141,39 +151,53 @@ namespace System.Xaml
manager.EndMember ();
var xm = members.Pop ();
var xt = xm.Type;
var contents = contents_stack.Peek ();
var state = object_states.Peek ();
var xt = state.Type;
var contents = state.Contents;
if (xm == XamlLanguage.Arguments) {
InitializeObjectWithArguments (contents.ToArray ());
throw new NotImplementedException ();
} else if (xm == XamlLanguage.Initialization) {
// ... and no need to do anything. The object value to pop *is* the return value.
} else if (xt.IsArray) {
} else if (xm.Type.IsArray) {
throw new NotImplementedException ();
} else if (xt.IsCollection) {
var obj = objects.Peek ();
} else if (xm == XamlLanguage.Items) {
var coll = state.Value;
foreach (var content in contents)
xt.Invoker.AddToCollection (obj, content);
} else if (xt.IsDictionary) {
xm.Type.Invoker.AddToCollection (coll, content);
} else if (xm.Type.IsDictionary) {
throw new NotImplementedException ();
} else {
if (contents.Count > 1)
throw new XamlDuplicateMemberException (String.Format ("Value for {0} is assigned more than once", xm.Name));
throw new XamlDuplicateMemberException (String.Format ("Property '{0}' is already set to this '{1}' object", xm, state.Type));
if (contents.Count == 1) {
var value = GetCorrectlyTypedValue (xm.Type, contents [0]);
if (!objects_from_getter.Remove (value))
var value = contents [0];
if (!xm.Type.IsCollection || !xm.IsReadOnly) // exclude read-only object.
SetValue (xm, value);
}
}
contents.Clear ();
written_properties_stack.Peek ().Add (xm);
if (object_states.Count > 0)
object_states.Peek ().WrittenProperties.Add (xm);
//written_properties_stack.Peek ().Add (xm);
}
object GetCorrectlyTypedValue (XamlType xt, object value)
{
// FIXME: this could be generalized by some means, but I cannot find any.
if (xt.UnderlyingType == typeof (Type))
xt = XamlLanguage.Type;
if (xt == XamlLanguage.Type && value is string)
value = new TypeExtension ((string) value);
if (value is MarkupExtension)
value = ((MarkupExtension) value).ProvideValue (service_provider);
if (IsAllowedType (xt, value))
return value;
if (xt.TypeConverter != null && value != null) {
var tc = xt.TypeConverter.ConverterInstance;
if (tc != null && tc.CanConvertFrom (value.GetType ()))
......@@ -181,30 +205,35 @@ namespace System.Xaml
if (IsAllowedType (xt, value))
return value;
}
throw new XamlObjectWriterException (String.Format ("Value is not of type {0}", xt));
throw new XamlObjectWriterException (String.Format ("Value '{1}' (of type {2}) is not of or convertible to type {0}", xt, value, value != null ? (object) value.GetType () : "(null)"));
}
bool IsAllowedType (XamlType xt, object value)
{
return xt == null || xt.UnderlyingType == null || xt.UnderlyingType.IsInstanceOfType (value);
return xt == null ||
xt.UnderlyingType == null ||
xt.UnderlyingType.IsInstanceOfType (value) ||
value == null && xt == XamlLanguage.Null ||
xt.IsMarkupExtension && IsAllowedType (xt.MarkupExtensionReturnType, value);
}
public override void WriteEndObject ()
{
manager.EndObject (types.Count > 0);
manager.EndObject (object_states.Count > 0);
InitializeObjectIfRequired (null); // this is required for such case that there was no StartMember call.
InitializeObjectIfRequired (false); // this is required for such case that there was no StartMember call.
types.Pop ();
contents_stack.Pop ();
written_properties_stack.Pop ();
var obj = objects.Pop ();
if (members.Count > 0)
contents_stack.Peek ().Add (obj);
if (objects.Count == 0) {
var ext = obj as MarkupExtension;
result = ext != null ? ext.ProvideValue (name_resolver) : obj;
var state = object_states.Pop ();
var xt = state.Type;
var obj = GetCorrectlyTypedValue (state.Type, state.Value);
if (members.Count > 0) {
var pstate = object_states.Peek ();
pstate.Contents.Add (obj);
pstate.WrittenProperties.Add (members.Peek ());
}
if (object_states.Count == 0)
result = obj;
}
public override void WriteGetObject ()
......@@ -212,18 +241,16 @@ namespace System.Xaml
manager.GetObject ();
var xm = members.Peek ();
// see GetObjectOnNonNullString() test
// see GetObjectOnNonNullString() test. Below is invalid.
//if (!xm.Type.IsCollection)
// throw new XamlObjectWriterException (String.Format ("WriteGetObject method can be invoked only when current member '{0}' is of collection type", xm.Name));
var obj = xm.Invoker.GetValue (objects.Peek ());
if (obj == null)
var instance = xm.Invoker.GetValue (object_states.Peek ().Value);
if (instance == null)
throw new XamlObjectWriterException (String.Format ("The value for '{0}' property is null", xm.Name));
types.Push (SchemaContext.GetXamlType (obj.GetType ()));
contents_stack.Push (new List<object> ());
ObjectInitialized (obj);
objects_from_getter.Add (obj);
var state = new ObjectState () {Type = SchemaContext.GetXamlType (instance.GetType ()), Value = instance, IsInstantiated = true, IsGetObject = true};
object_states.Push (state);
}
public override void WriteNamespace (NamespaceDeclaration namespaceDeclaration)
......@@ -233,7 +260,7 @@ namespace System.Xaml
manager.Namespace ();
// FIXME: find out what to do.
namespaces.Add (namespaceDeclaration);
}
public override void WriteStartMember (XamlMember property)
......@@ -243,34 +270,34 @@ namespace System.Xaml
manager.StartMember ();
var wpl = written_properties_stack.Peek ();
if (wpl.Contains (property))
throw new XamlDuplicateMemberException (String.Format ("Property '{0}' is already set to this '{1}' object", property.Name, types.Peek ().Name));
wpl.Add (property);
var wpl = object_states.Peek ().WrittenProperties;
// FIXME: enable this. Duplicate property check should
// be differentiate from duplicate contents (both result
// in XamlDuplicateMemberException though).
// Now it is done at WriteStartObject/WriteValue, but
// it is simply wrong.
// if (wpl.Contains (property))
// throw new XamlDuplicateMemberException (String.Format ("Property '{0}' is already set to this '{1}' object", property, object_states.Peek ().Type));
// wpl.Add (property);
members.Push (property);
}
void InitializeObjectWithArguments (object [] args)
void InitializeObjectIfRequired (bool isStart)
{
var obj = types.Peek ().Invoker.CreateInstance (args);
ObjectInitialized (obj);
}
void InitializeObjectIfRequired (XamlMember property)
{
if (object_instantiated)
var state = object_states.Peek ();
if (state.IsInstantiated)
return;
// FIXME: "The default techniques in absence of a factory method are to attempt to find a default constructor, then attempt to find an identified type converter on type, member, or destination type."
// http://msdn.microsoft.com/en-us/library/system.xaml.xamllanguage.factorymethod%28VS.100%29.aspx
object obj;
var args = arguments.ToArray ();
if (factory_method != null) // FIXME: it must be verified with tests.
obj = types.Peek ().UnderlyingType.GetMethod (factory_method).Invoke (null, args);
if (state.FactoryMethod != null) // FIXME: it must be implemented and verified with tests.
throw new NotImplementedException ();
else
obj = types.Peek ().Invoker.CreateInstance (args);
ObjectInitialized (obj);
obj = state.Type.Invoker.CreateInstance (null);
state.Value = obj;
state.IsInstantiated = true;
}
public override void WriteStartObject (XamlType xamlType)
......@@ -280,15 +307,20 @@ namespace System.Xaml
manager.StartObject ();
types.Push (xamlType);
contents_stack.Push (new List<object> ());
var xm = members.Count > 0 ? members.Peek () : null;
var pstate = xm != null ? object_states.Peek () : null;
var wpl = xm != null && xm != XamlLanguage.Items ? pstate.WrittenProperties : null;
if (wpl != null && wpl.Contains (xm))
throw new XamlDuplicateMemberException (String.Format ("Property '{0}' is already set to this '{1}' object", xm, pstate.Type));
object_instantiated = false;
var cstate = new ObjectState () {Type = xamlType, IsInstantiated = false};
object_states.Push (cstate);
written_properties_stack.Push (new List<XamlMember> ());
if (!xamlType.IsContentValue ()) // FIXME: there could be more conditions e.g. the type requires Arguments.
InitializeObjectIfRequired (true);
if (!xamlType.IsContentValue ()) // FIXME: there could be more conditions.
InitializeObjectIfRequired (null);
if (wpl != null) // note that this adds to the *owner* object's properties.
wpl.Add (xm);
}
public override void WriteValue (object value)
......@@ -296,21 +328,93 @@ namespace System.Xaml
manager.Value ();
var xm = members.Peek ();
var state = object_states.Peek ();
var wpl = xm != null && xm != XamlLanguage.Items ? state.WrittenProperties : null;
if (wpl != null && wpl.Contains (xm))
throw new XamlDuplicateMemberException (String.Format ("Property '{0}' is already set to this '{1}' object", xm, state.Type));
if (xm == XamlLanguage.Initialization)
ObjectInitialized (GetCorrectlyTypedValue (types.Peek (), value));
if (xm == XamlLanguage.Initialization ||
xm == state.Type.ContentProperty) {
value = GetCorrectlyTypedValue (state.Type, value);
state.Value = value;
state.IsInstantiated = true;
}
else if (xm == XamlLanguage.FactoryMethod)
factory_method = (string) value;
state.FactoryMethod = (string) value;
// else if (xm.Type.IsCollection)
else if (xm == XamlLanguage.Items) // FIXME: am not sure which is good yet.
state.Contents.Add (GetCorrectlyTypedValue (xm.Type.ItemType, value));
else
contents_stack.Peek ().Add (value);
state.Contents.Add (GetCorrectlyTypedValue (xm.Type, value));
if (wpl != null)
wpl.Add (xm);
}
class XamlObjectWriterServiceProvider : IServiceProvider
{
XamlNameResolver name_resolver = new XamlNameResolver ();
XamlTypeResolver type_resolver;
NamespaceResolver namespace_resolver;
public XamlObjectWriterServiceProvider (XamlObjectWriter writer)
{
namespace_resolver = new NamespaceResolver (writer.namespaces);
type_resolver = new XamlTypeResolver (namespace_resolver, writer.SchemaContext);
}
public object GetService (Type serviceType)
{
if (serviceType == typeof (IXamlNamespaceResolver))
return namespace_resolver;
if (serviceType == typeof (IXamlNameResolver))
return name_resolver;
if (serviceType == typeof (IXamlTypeResolver))
return type_resolver;
return null;
}
}
internal class XamlTypeResolver : IXamlTypeResolver
{
NamespaceResolver ns_resolver;
XamlSchemaContext schema_context;
public XamlTypeResolver (NamespaceResolver namespaceResolver, XamlSchemaContext schemaContext)
{
ns_resolver = namespaceResolver;
schema_context = schemaContext;
}
void ObjectInitialized (object obj)
public Type Resolve (string typeName)
{
objects.Push (obj);
object_instantiated = true;
arguments.Clear ();
factory_method = null;
var tn = XamlTypeName.Parse (typeName, ns_resolver);
var xt = schema_context.GetXamlType (tn);
return xt != null ? xt.UnderlyingType : null;
}
}
internal class NamespaceResolver : IXamlNamespaceResolver
{
public NamespaceResolver (List<NamespaceDeclaration> source)
{
this.source = source;
}
List<NamespaceDeclaration> source;
public string GetNamespace (string prefix)
{
foreach (var nsd in source)
if (nsd.Prefix == prefix)
return nsd.Namespace;
return null;
}
public IEnumerable<NamespaceDeclaration> GetNamespacePrefixes ()
{
return source;
}
}
}
}
System.Windows.Markup/ArrayExtensionTest.cs
System.Windows.Markup/ReferenceTest.cs
System.Windows.Markup/StaticExtensionTest.cs
System.Windows.Markup/TypeExtensionConverterTest.cs
System.Windows.Markup/TypeExtensionTest.cs
System.Windows.Markup/ValueSerializerTest.cs
System.Windows.Markup/XDataTest.cs
......
//
// 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.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 ReferenceTest
{
[Test]
public void ConstructorNullName ()
{
new Reference ((string) null); // it is somehow allowed
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void ProvideValueWithoutTypeOrName ()
{
new Reference ().ProvideValue (null);
}
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void ProvideValueWithNameWithoutResolver ()
{
var x = new Reference ("X");
x.ProvideValue (null); // serviceProvider is required.
}
[Test]
[ExpectedException (typeof (InvalidOperationException))]
public void ProvideValueWithNameWithProviderNoResolver ()
{
var x = new Reference ("X");
x.ProvideValue (new NameServiceProvider (false, false));
}
[Test]
public void ProvideValueWithNameWithProviderResolveFail ()
{
var x = new Reference ("X");
var r = new NameServiceProvider (true, false);
Assert.AreEqual ("BAR", x.ProvideValue (r), "#1");
}
[Test]
public void ProvideValueWithNameWithProviderResolveSuccess ()
{
var x = new Reference ("X");
var r = new NameServiceProvider (true, true);
Assert.AreEqual ("FOO", x.ProvideValue (r), "#1");
}
class NameServiceProvider : IServiceProvider
{
Resolver resolver;
public NameServiceProvider (bool worksFine, bool resolvesFine)
{
resolver = worksFine ? new Resolver (resolvesFine) : null;
}
public object GetService (Type serviceType)
{
Assert.AreEqual (typeof (IXamlNameResolver), serviceType, "TypeToResolve");
return resolver;
}
}
class Resolver : IXamlNameResolver
{
bool resolves;
public Resolver (bool resolvesFine)
{
resolves = resolvesFine;
}
public IEnumerable<KeyValuePair<string, object>> GetAllNamesAndValuesInScope ()
{
throw new Exception ();
}
public object GetFixupToken (IEnumerable<string> names)
{
throw new NotImplementedException ();
}
public object GetFixupToken (IEnumerable<string> names, bool canAssignDirectly)
{
Assert.IsTrue (canAssignDirectly, "canAssignDirectly");
Assert.AreEqual (1, names.Count (), "Count");
return "BAR";
}
public bool IsFixupTokenAvailable {
get { throw new NotImplementedException (); }
}
public event EventHandler OnNameScopeInitializationComplete;
public object Resolve (string name)
{
return resolves ? "FOO" : null;
}
public object Resolve (string name, out bool isFullyInitialized)
{
throw new NotImplementedException ();
}
}
}
}
//
// 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.ComponentModel.Design.Serialization;
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 TypeExtensionConverterTest
{
class XamlTypeResolver : IXamlTypeResolver
{
public Type Resolve (string qualifiedTypeName)
{
throw new NotImplementedException ();
}
}
class TypeDescriptorContext : ITypeDescriptorContext
{
public object Service { get; set; }
public object GetService (Type serviceType)
{
return Service != null && serviceType.IsAssignableFrom (Service.GetType ()) ? Service : null;
}
public void OnComponentChanged ()
{
}
public bool OnComponentChanging ()
{
return true;
}
public IContainer Container { get; set; }
public object Instance { get; set; }
public PropertyDescriptor PropertyDescriptor { get; set; }
}
[Test]
public void CanConvertFrom ()
{
var tc = XamlLanguage.Type.TypeConverter.ConverterInstance;
Assert.IsFalse (tc.CanConvertFrom (null, typeof (string)), "#1");
Assert.IsFalse (tc.CanConvertFrom (null, typeof (Type)), "#2");
Assert.IsFalse (tc.CanConvertFrom (null, typeof (Type)), "#3");
Assert.IsTrue (tc.CanConvertFrom (null, typeof (InstanceDescriptor)), "#4");
var idc = new TypeDescriptorContext () {Instance = "x:Int32", Service = new XamlTypeResolver ()}; // gives no difference ...
Assert.IsFalse (tc.CanConvertFrom (idc, typeof (string)), "#5");
Assert.IsFalse (tc.CanConvertFrom (idc, typeof (Type)), "#6");
Assert.IsFalse (tc.CanConvertFrom (idc, typeof (TypeExtension)), "#7");
}
[Test]
public void CanConvertTo ()
{
var tc = XamlLanguage.Type.TypeConverter.ConverterInstance;
Assert.IsTrue (tc.CanConvertTo (null, typeof (string)), "#1");
Assert.IsFalse (tc.CanConvertTo (null, typeof (Type)), "#2");
Assert.IsFalse (tc.CanConvertTo (null, typeof (TypeExtension)), "#3");
var idc = new TypeDescriptorContext () {Instance = "x:Int32", Service = new XamlTypeResolver ()}; // gives no differences...
Assert.IsTrue (tc.CanConvertTo (idc, typeof (string)), "#5");
Assert.IsFalse (tc.CanConvertTo (idc, typeof (Type)), "#6");
Assert.IsFalse (tc.CanConvertTo (idc, typeof (TypeExtension)), "#7");
}
[Test]
public void ConvertTo ()
{
var tc = XamlLanguage.Type.TypeConverter.ConverterInstance;
Assert.AreEqual ("x:Int32", tc.ConvertTo (null, null, "x:Int32", typeof (string)), "#1");
Assert.AreEqual ("System.Int32", tc.ConvertTo (null, null, typeof (int), typeof (string)), "#2");
Assert.AreEqual ("System.Type", tc.ConvertTo (null, null, typeof (Type), typeof (string)), "#3");
}
[Test]
[ExpectedException (typeof (NotSupportedException))]
public void ConvertToFail ()
{
var tc = XamlLanguage.Type.TypeConverter.ConverterInstance;
tc.ConvertTo (null, null, typeof (int), typeof (Type));
}
[Test]
[ExpectedException (typeof (NotSupportedException))]
public void ConvertToFail2 ()
{
var tc = XamlLanguage.Type.TypeConverter.ConverterInstance;
tc.ConvertTo (null, null, "x:Int32", typeof (TypeExtension));
}
}
}
......@@ -58,6 +58,8 @@ namespace MonoTests.System.Xaml.Schema
{
}
// SetMarkupExtensionHandler
[Test]
[ExpectedException (typeof (ArgumentException))]
public void SetHandleMarkupExtensionInvalid ()
......@@ -116,6 +118,8 @@ namespace MonoTests.System.Xaml.Schema
Assert.IsNotNull (i.SetMarkupExtensionHandler, "#1");
}
// SetTypeConverterHandler
[XamlSetTypeConverter ("HandleTypeConverter")]
public class TestClassTypeConverter1
{
......@@ -178,5 +182,135 @@ namespace MonoTests.System.Xaml.Schema
var i = new XamlTypeInvoker (new XamlType (typeof (TestClassTypeConverter4), sctx));
Assert.IsNotNull (i.SetTypeConverterHandler, "#1");
}
// AddToCollection
[Test]
public void AddToCollectionNoUnderlyingType ()
{
var i = new XamlTypeInvoker (new XamlType ("urn:foo", "FooType", null, sctx));
i.AddToCollection (new List<int> (), 5); // ... passes.
}
[Test]
[ExpectedException (typeof (NotSupportedException))]
public void AddToCollectionArrayExtension ()
{
var i = XamlLanguage.Array.Invoker;
var ax = new ArrayExtension ();
i.AddToCollection (ax, 5);
}
[Test]
[ExpectedException (typeof (NotSupportedException))]
public void AddToCollectionArrayInstance ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (int []), sctx));
var ax = new ArrayExtension ();
i.AddToCollection (ax, 5);
}
[Test]
public void AddToCollectionList_ObjectTypeMismatch ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (List<int>), sctx));
try {
i.AddToCollection (new ArrayExtension (), 5);
Assert.Fail ("not supported operation.");
} catch (NotSupportedException) {
} catch (TargetException) {
// .NET throws this, but the difference should not really matter.
}
}
[Test]
public void AddToCollectionList_ObjectTypeMismatch2 ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (List<int>), sctx));
i.AddToCollection (new List<object> (), 5); // it is allowed.
}
[Test]
public void AddToCollectionList_ObjectTypeMismatch3 ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (List<object>), sctx));
i.AddToCollection (new List<int> (), 5); // it is allowed too.
}
[Test]
public void AddToCollectionList_ObjectTypeMismatch4 ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (List<Uri>), sctx));
i.AddToCollection (new List<TimeSpan> (), TimeSpan.Zero); // it is allowed too.
}
[Test]
public void AddToCollectionList_NonCollectionType ()
{
// so, the source collection type is not checked at all.
var i = new XamlTypeInvoker (new XamlType (typeof (Uri), sctx));
i.AddToCollection (new List<TimeSpan> (), TimeSpan.Zero); // it is allowed too.
}
[Test]
public void AddToCollectionList ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (List<int>), sctx));
var l = new List<int> ();
i.AddToCollection (l, 5);
i.AddToCollection (l, 3);
i.AddToCollection (l, -12);
Assert.AreEqual (3, l.Count, "#1");
Assert.AreEqual (-12, l [2], "#2");
}
[Test]
[ExpectedException (typeof (ArgumentException))]
public void AddToCollectionTypeMismatch ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (List<int>), sctx));
var l = new List<int> ();
i.AddToCollection (l, "5");
}
// CreateInstance
[Test]
[ExpectedException (typeof (NotSupportedException))]
public void CreateInstanceNoUnderlyingType ()
{
var i = new XamlTypeInvoker (new XamlType ("urn:foo", "FooType", null, sctx));
i.CreateInstance (new object [0]); // unkown type is not supported
}
[Test]
public void CreateInstanceArrayExtension ()
{
var i = XamlLanguage.Array.Invoker;
i.CreateInstance (new object [0]);
}
[Test]
[ExpectedException (typeof (MissingMethodException))]
public void CreateInstanceArray ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (int []), sctx));
i.CreateInstance (new object [0]); // no default constructor.
}
[Test]
[ExpectedException (typeof (MissingMethodException))]
public void CreateInstanceList_ArgumentMismatch ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (List<int>), sctx));
i.CreateInstance (new object [] {"foo"});
}
[Test]
public void CreateInstanceList ()
{
var i = new XamlTypeInvoker (new XamlType (typeof (List<int>), sctx));
i.CreateInstance (new object [0]);
}
}
}
\ No newline at end of file
......@@ -445,6 +445,7 @@ namespace MonoTests.System.Xaml
{
var m = XamlLanguage.Type.GetMember ("Type");
TestMemberCommon (m, "Type", typeof (Type), typeof (TypeExtension), true);
Assert.AreNotEqual (XamlLanguage.Type, m.Type, "#1");
}
// primitive types
......@@ -802,6 +803,7 @@ namespace MonoTests.System.Xaml
Assert.IsNotNull (t.TypeConverter, "#25");
Assert.IsNotNull (t.MarkupExtensionReturnType, "#29");
Assert.AreEqual (extReturnType, t.MarkupExtensionReturnType.UnderlyingType, "#29-2");
Assert.IsNull (t.Invoker.SetMarkupExtensionHandler, "#31"); // orly?
}
void TestMemberCommon (XamlMember m, string name, Type type, Type declType, bool hasSetter)
......
......@@ -254,6 +254,7 @@ namespace MonoTests.System.Xaml
}
[Test]
[ExpectedException (typeof (XamlDuplicateMemberException))]
public void ValueAfterObject2 ()
{
var xw = new XamlObjectWriter (sctx, null);
......@@ -263,6 +264,8 @@ namespace MonoTests.System.Xaml
xw.WriteEndObject ();
// passes here, but should be rejected later.
xw.WriteValue ("foo");
xw.WriteEndMember (); // Though this raises an error.
}
[Test]
......@@ -280,6 +283,7 @@ namespace MonoTests.System.Xaml
[Test]
[ExpectedException (typeof (XamlDuplicateMemberException))]
[Category ("NotWorking")]
public void DuplicateAssignment2 ()
{
var xw = new XamlObjectWriter (sctx, null);
......@@ -432,6 +436,7 @@ namespace MonoTests.System.Xaml
}
[Test]
[ExpectedException (typeof (XamlDuplicateMemberException))] // duplicate member assignment
public void ObjectContainsObjectAndValue ()
{
var xw = new XamlObjectWriter (sctx, null);
......@@ -440,6 +445,8 @@ namespace MonoTests.System.Xaml
xw.WriteStartObject (xt3);
xw.WriteEndObject ();
xw.WriteValue ("foo"); // but this is allowed ...
xw.WriteEndMember (); // Though this raises an error.
}
[Test]
......
......@@ -344,8 +344,7 @@ namespace MonoTests.System.Xaml
Assert.IsFalse (t.IsAmbient, "#22");
Assert.IsNull (t.AllowedContentTypes, "#23");
Assert.IsNull (t.ContentWrappers, "#24");
// FIXME: enable this when we fixed TypeConverter for Type.
//Assert.IsNotNull (t.TypeConverter, "#25"); // TypeTypeConverter
Assert.IsNotNull (t.TypeConverter, "#25"); // TypeTypeConverter
Assert.IsNull (t.ValueSerializer, "#26");
Assert.IsNull (t.ContentProperty, "#27");
//Assert.IsNull (t.DeferringLoader, "#28");
......
......@@ -115,7 +115,9 @@ namespace MonoTests.System.Xaml
public void Read_ArrayInt32 ()
{
ReadTest ("Array_Int32.xml");
//LoadTest<int[]> ("Array_Int32.xml");
var ret = LoadTest<int[]> ("Array_Int32.xml");
Assert.AreEqual (5, ret.Length, "#1");
Assert.AreEqual (2147483647, ret [4], "#2");
}
[Test]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册