Merge pull request #961 from ermshiperete/bug-xamarin-18118
[mono.git] / mcs / class / System.Xaml / System.Xaml / XamlType.cs
old mode 100644 (file)
new mode 100755 (executable)
index 26bdf97..6aebc3e
@@ -28,6 +28,7 @@ using System.Linq;
 using System.Reflection;
 using System.Windows.Markup;
 using System.Xaml.Schema;
+using System.Xml.Serialization;
 
 namespace System.Xaml
 {
@@ -38,9 +39,9 @@ namespace System.Xaml
                {
                }
 
-               static readonly Type [] predefined_types = {
-                               typeof (XData), typeof (Uri), typeof (TimeSpan), typeof (PropertyDefinition), typeof (MemberDefinition), typeof (Reference)
-                       };
+//             static readonly Type [] predefined_types = {
+//                             typeof (XData), typeof (Uri), typeof (TimeSpan), typeof (PropertyDefinition), typeof (MemberDefinition), typeof (Reference)
+//                     };
 
                public XamlType (Type underlyingType, XamlSchemaContext schemaContext, XamlTypeInvoker invoker)
                        : this (schemaContext, invoker)
@@ -50,16 +51,28 @@ namespace System.Xaml
                        type = underlyingType;
                        underlying_type = type;
 
-                       Name = type.GetXamlName ();
-                       // FIXME: remove this hack
-                       if (Type.GetTypeCode (type) == TypeCode.Object && type != typeof (object)) {
-                               if (predefined_types.Contains (type) || typeof (MarkupExtension).IsAssignableFrom (type) && type.Assembly == typeof (XamlType).Assembly)
-                                       PreferredXamlNamespace = XamlLanguage.Xaml2006Namespace;
+                       XamlType xt;
+                       if (XamlLanguage.InitializingTypes) {
+                               // These are special. Only XamlLanguage members are with shorthand name.
+                               if (type == typeof (PropertyDefinition))
+                                       Name = "Property";
+                               else if (type == typeof (MemberDefinition))
+                                       Name = "Member";
                                else
-                                       PreferredXamlNamespace = String.Format ("clr-namespace:{0};assembly={1}", type.Namespace, type.Assembly.GetName ().Name);
-                       }
-                       else
+                                       Name = GetXamlName (type);
                                PreferredXamlNamespace = XamlLanguage.Xaml2006Namespace;
+                       } else if ((xt = XamlLanguage.AllTypes.FirstOrDefault (t => t.UnderlyingType == type)) != null) {
+                               Name = xt.Name;
+                               PreferredXamlNamespace = XamlLanguage.Xaml2006Namespace;
+                       } else {
+                               Name = GetXamlName (type);
+                               PreferredXamlNamespace = schemaContext.GetXamlNamespace (type.Namespace) ?? String.Format ("clr-namespace:{0};assembly={1}", type.Namespace, type.Assembly.GetName ().Name);
+                       }
+                       if (type.IsGenericType) {
+                               TypeArguments = new List<XamlType> ();
+                               foreach (var gta in type.GetGenericArguments ())
+                                       TypeArguments.Add (schemaContext.GetXamlType (gta));
+                       }
                }
 
                public XamlType (string unknownTypeNamespace, string unknownTypeName, IList<XamlType> typeArguments, XamlSchemaContext schemaContext)
@@ -76,6 +89,7 @@ namespace System.Xaml
                        Name = unknownTypeName;
                        PreferredXamlNamespace = unknownTypeNamespace;
                        TypeArguments = typeArguments != null && typeArguments.Count == 0 ? null : typeArguments;
+//                     explicit_ns = unknownTypeNamespace;
                }
 
                protected XamlType (string typeName, IList<XamlType> typeArguments, XamlSchemaContext schemaContext)
@@ -93,6 +107,8 @@ namespace System.Xaml
 
                Type type, underlying_type;
 
+//             string explicit_ns;
+
                // populated properties
                XamlType base_type;
                XamlTypeInvoker invoker;
@@ -136,12 +152,14 @@ namespace System.Xaml
                public bool IsAmbient {
                        get { return LookupIsAmbient (); }
                }
+
                public bool IsArray {
-                       get { return type.IsArray; }
+                       get { return LookupCollectionKind () == XamlCollectionKind.Array; }
                }
+
+               // it somehow treats array as not a collection...
                public bool IsCollection {
-                       // it somehow treats array as not a collection...
-                       get { return !type.IsArray && type.ImplementsAnyInterfacesOf (typeof (ICollection), typeof (ICollection<>)); }
+                       get { return LookupCollectionKind () == XamlCollectionKind.Collection; }
                }
 
                public bool IsConstructible {
@@ -149,7 +167,7 @@ namespace System.Xaml
                }
 
                public bool IsDictionary {
-                       get { return type.ImplementsAnyInterfacesOf (typeof (IDictionary), typeof (IDictionary<,>)); }
+                       get { return LookupCollectionKind () == XamlCollectionKind.Dictionary; }
                }
 
                public bool IsGeneric {
@@ -226,6 +244,14 @@ namespace System.Xaml
                        get { return LookupValueSerializer (); }
                }
 
+               internal string GetInternalXmlName ()
+               {
+                       if (IsMarkupExtension && Name.EndsWith ("Extension", StringComparison.Ordinal))
+                               return Name.Substring (0, Name.Length - 9);
+                       var stn = XamlLanguage.SpecialNames.FirstOrDefault (s => s.Type == this);
+                       return stn != null ? stn.Name : Name;
+               }
+
                public static bool operator == (XamlType left, XamlType right)
                {
                        return IsNull (left) ? IsNull (right) : left.Equals (right);
@@ -243,25 +269,11 @@ namespace System.Xaml
                
                public bool Equals (XamlType other)
                {
+                       // It does not compare XamlSchemaContext.
                        return !IsNull (other) &&
                                UnderlyingType == other.UnderlyingType &&
                                Name == other.Name &&
-                               PreferredXamlNamespace == other.PreferredXamlNamespace &&
-                               CompareTypes (TypeArguments, other.TypeArguments);
-               }
-
-               static bool CompareTypes (IList<XamlType> a1, IList<XamlType> a2)
-               {
-                       if (a1 == null)
-                               return a2 == null;
-                       if (a2 == null)
-                               return false;
-                       if (a1.Count != a2.Count)
-                               return false;
-                       for (int i = 0; i < a1.Count; i++)
-                               if (a1 [i] != a2 [i])
-                                       return false;
-                       return true;
+                               PreferredXamlNamespace == other.PreferredXamlNamespace && TypeArguments.ListEquals (other.TypeArguments);
                }
 
                public override bool Equals (object obj)
@@ -283,12 +295,16 @@ namespace System.Xaml
 
                public override string ToString ()
                {
-                       return UnderlyingType != null ? UnderlyingType.ToString () : Name;
+                       return new XamlTypeName (this).ToString ();
+                       //return String.IsNullOrEmpty (PreferredXamlNamespace) ? Name : String.Concat ("{", PreferredXamlNamespace, "}", Name);
                }
 
                public virtual bool CanAssignTo (XamlType xamlType)
                {
-                       throw new NotImplementedException ();
+                       if (this.UnderlyingType == null)
+                               return xamlType == XamlLanguage.Object;
+                       var ut = xamlType.UnderlyingType ?? typeof (object);
+                       return ut.IsAssignableFrom (UnderlyingType);
                }
 
                public XamlMember GetAliasedProperty (XamlDirective directive)
@@ -313,7 +329,7 @@ namespace System.Xaml
 
                public XamlMember GetMember (string name)
                {
-                       return LookupMember (name, false);
+                       return LookupMember (name, true);
                }
 
                public IList<XamlType> GetPositionalParameters (int parameterCount)
@@ -324,47 +340,203 @@ namespace System.Xaml
                public virtual IList<string> GetXamlNamespaces ()
                {
                        throw new NotImplementedException ();
+                       /* this does not work like documented!
+                       if (explicit_ns != null)
+                               return new string [] {explicit_ns};
+                       var l = SchemaContext.GetAllXamlNamespaces ();
+                       if (l != null)
+                               return new List<string> (l);
+                       return new string [] {String.Empty};
+                       */
                }
 
                // lookups
 
                protected virtual XamlMember LookupAliasedProperty (XamlDirective directive)
                {
-                       throw new NotImplementedException ();
+                       if (directive == XamlLanguage.Key) {
+                               var a = this.GetCustomAttribute<DictionaryKeyPropertyAttribute> ();
+                               return a != null ? GetMember (a.Name) : null;
+                       }
+                       if (directive == XamlLanguage.Name) {
+                               var a = this.GetCustomAttribute<RuntimeNamePropertyAttribute> ();
+                               return a != null ? GetMember (a.Name) : null;
+                       }
+                       if (directive == XamlLanguage.Uid) {
+                               var a = this.GetCustomAttribute<UidPropertyAttribute> ();
+                               return a != null ? GetMember (a.Name) : null;
+                       }
+                       if (directive == XamlLanguage.Lang) {
+                               var a = this.GetCustomAttribute<XmlLangPropertyAttribute> ();
+                               return a != null ? GetMember (a.Name) : null;
+                       }
+                       return null;
                }
+
                protected virtual IEnumerable<XamlMember> LookupAllAttachableMembers ()
                {
-                       throw new NotImplementedException ();
+                       if (UnderlyingType == null)
+                               return BaseType != null ? BaseType.GetAllAttachableMembers () : empty_array;
+                       if (all_attachable_members_cache == null) {
+                               all_attachable_members_cache = new List<XamlMember> (DoLookupAllAttachableMembers ());
+                               all_attachable_members_cache.Sort (TypeExtensionMethods.CompareMembers);
+                       }
+                       return all_attachable_members_cache;
+               }
+
+               IEnumerable<XamlMember> DoLookupAllAttachableMembers ()
+               {
+                       // based on http://msdn.microsoft.com/en-us/library/ff184560.aspx
+                       var bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
+
+                       var gl = new Dictionary<string,MethodInfo> ();
+                       var sl = new Dictionary<string,MethodInfo> ();
+                       var al = new Dictionary<string,MethodInfo> ();
+                       //var rl = new Dictionary<string,MethodInfo> ();
+                       var nl = new List<string> ();
+                       foreach (var mi in UnderlyingType.GetMethods (bf)) {
+                               string name = null;
+                               if (mi.Name.StartsWith ("Get", StringComparison.Ordinal)) {
+                                       if (mi.ReturnType == typeof (void))
+                                               continue;
+                                       var args = mi.GetParameters ();
+                                       if (args.Length != 1)
+                                               continue;
+                                       name = mi.Name.Substring (3);
+                                       gl.Add (name, mi);
+                               } else if (mi.Name.StartsWith ("Set", StringComparison.Ordinal)) {
+                                       // looks like the return type is *ignored*
+                                       //if (mi.ReturnType != typeof (void))
+                                       //      continue;
+                                       var args = mi.GetParameters ();
+                                       if (args.Length != 2)
+                                               continue;
+                                       name = mi.Name.Substring (3);
+                                       sl.Add (name, mi);
+                               } else if (mi.Name.EndsWith ("Handler", StringComparison.Ordinal)) {
+                                       var args = mi.GetParameters ();
+                                       if (args.Length != 2)
+                                               continue;
+                                       if (mi.Name.StartsWith ("Add", StringComparison.Ordinal)) {
+                                               name = mi.Name.Substring (3, mi.Name.Length - 3 - 7);
+                                               al.Add (name, mi);
+                                       }/* else if (mi.Name.StartsWith ("Remove", StringComparison.Ordinal)) {
+                                               name = mi.Name.Substring (6, mi.Name.Length - 6 - 7);
+                                               rl.Add (name, mi);
+                                       }*/
+                               }
+                               if (name != null && !nl.Contains (name))
+                                       nl.Add (name);
+                       }
+
+                       foreach (var name in nl) {
+                               MethodInfo m;
+                               var g = gl.TryGetValue (name, out m) ? m : null;
+                               var s = sl.TryGetValue (name, out m) ? m : null;
+                               if (g != null || s != null)
+                                       yield return new XamlMember (name, g, s, SchemaContext);
+                               var a = al.TryGetValue (name, out m) ? m : null;
+                               //var r = rl.TryGetValue (name, out m) ? m : null;
+                               if (a != null)
+                                       yield return new XamlMember (name, a, SchemaContext);
+                       }
                }
+
+               static readonly XamlMember [] empty_array = new XamlMember [0];
+
                protected virtual IEnumerable<XamlMember> LookupAllMembers ()
                {
-                       throw new NotImplementedException ();
+                       if (UnderlyingType == null)
+                               return BaseType != null ? BaseType.GetAllMembers () : empty_array;
+                       if (all_members_cache == null) {
+                               all_members_cache = new List<XamlMember> (DoLookupAllMembers ());
+                               all_members_cache.Sort (TypeExtensionMethods.CompareMembers);
+                       }
+                       return all_members_cache;
+               }
+               
+               List<XamlMember> all_members_cache;
+               List<XamlMember> all_attachable_members_cache;
+
+               IEnumerable<XamlMember> DoLookupAllMembers ()
+               {
+                       // This is a hack that is likely required due to internal implementation difference in System.Uri. Our Uri has two readonly collection properties
+                       if (this == XamlLanguage.Uri)
+                               yield break;
+
+                       var bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
+
+                       foreach (var pi in UnderlyingType.GetProperties (bf)) {
+                               if (pi.Name.Contains ('.')) // exclude explicit interface implementations.
+                                       continue;
+                               if (pi.CanRead && (pi.CanWrite || IsCollectionType (pi.PropertyType) || typeof (IXmlSerializable).IsAssignableFrom (pi.PropertyType)) && pi.GetIndexParameters ().Length == 0)
+                                       yield return new XamlMember (pi, SchemaContext);
+                       }
+                       foreach (var ei in UnderlyingType.GetEvents (bf))
+                               yield return new XamlMember (ei, SchemaContext);
                }
+               
+               static bool IsPublicAccessor (MethodInfo mi)
+               {
+                       return mi != null && mi.IsPublic;
+               }
+
+               bool IsCollectionType (Type type)
+               {
+                       if (type == null)
+                               return false;
+                       var xt = SchemaContext.GetXamlType (type);
+                       return xt.LookupCollectionKind () != XamlCollectionKind.None;
+               }
+
                protected virtual IList<XamlType> LookupAllowedContentTypes ()
                {
-                       throw new NotImplementedException ();
+                       // the actual implementation is very different from what is documented :(
+                       return null;
+
+                       /*
+                       var l = new List<XamlType> ();
+                       if (ContentWrappers != null)
+                               l.AddRange (ContentWrappers);
+                       if (ContentProperty != null)
+                               l.Add (ContentProperty.Type);
+                       if (ItemType != null)
+                               l.Add (ItemType);
+                       return l.Count > 0 ? l : null;
+                       */
                }
+
                protected virtual XamlMember LookupAttachableMember (string name)
                {
-                       throw new NotImplementedException ();
+                       return GetAllAttachableMembers ().FirstOrDefault (m => m.Name == name);
                }
 
-               [MonoTODO]
                protected virtual XamlType LookupBaseType ()
                {
                        if (base_type == null) {
                                if (UnderlyingType == null)
-                                       // FIXME: probably something advanced is needed here.
-                                       base_type = new XamlType (typeof (object), SchemaContext, Invoker);
+                                       base_type = SchemaContext.GetXamlType (typeof (object));
                                else
-                                       base_type = type.BaseType == null || type.BaseType == typeof (object) ? null : new XamlType (type.BaseType, SchemaContext, Invoker);
+                                       base_type = type.BaseType == null || type.BaseType == typeof (object) ? null : SchemaContext.GetXamlType (type.BaseType);
                        }
                        return base_type;
                }
 
-               protected virtual XamlCollectionKind LookupCollectionKind ()
+               // This implementation is not verified. (No place to use.)
+               protected internal virtual XamlCollectionKind LookupCollectionKind ()
                {
-                       throw new NotImplementedException ();
+                       if (UnderlyingType == null)
+                               return BaseType != null ? BaseType.LookupCollectionKind () : XamlCollectionKind.None;
+                       if (type.IsArray)
+                               return XamlCollectionKind.Array;
+
+                       if (type.ImplementsAnyInterfacesOf (typeof (IDictionary), typeof (IDictionary<,>)))
+                               return XamlCollectionKind.Dictionary;
+
+                       if (type.ImplementsAnyInterfacesOf (typeof (IList), typeof (ICollection<>)))
+                               return XamlCollectionKind.Collection;
+
+                       return XamlCollectionKind.None;
                }
 
                protected virtual bool LookupConstructionRequiresArguments ()
@@ -372,7 +544,7 @@ namespace System.Xaml
                        if (UnderlyingType == null)
                                return false;
 
-                       // not sure if it is required, but TypeDefinition and MemberDefinition return true while they are abstract and it makes no sense.
+                       // not sure if it is required, but MemberDefinition return true while they are abstract and it makes no sense.
                        if (UnderlyingType.IsAbstract)
                                return true;
 
@@ -396,14 +568,31 @@ namespace System.Xaml
                        var a = this.GetCustomAttribute<ContentPropertyAttribute> ();
                        return a != null && a.Name != null ? GetMember (a.Name) : null;
                }
+
                protected virtual IList<XamlType> LookupContentWrappers ()
                {
-                       throw new NotImplementedException ();
+                       if (GetCustomAttributeProvider () == null)
+                               return null;
+
+                       var arr = GetCustomAttributeProvider ().GetCustomAttributes (typeof (ContentWrapperAttribute), false);
+                       if (arr == null || arr.Length == 0)
+                               return null;
+                       var l = new XamlType [arr.Length];
+                       for (int i = 0; i < l.Length; i++) 
+                               l [i] = SchemaContext.GetXamlType (((ContentWrapperAttribute) arr [i]).ContentWrapper);
+                       return l;
                }
-               protected virtual ICustomAttributeProvider LookupCustomAttributeProvider ()
+
+               internal ICustomAttributeProvider GetCustomAttributeProvider ()
                {
-                       throw new NotImplementedException ();
+                       return LookupCustomAttributeProvider ();
                }
+
+               protected internal virtual ICustomAttributeProvider LookupCustomAttributeProvider ()
+               {
+                       return UnderlyingType;
+               }
+               
                protected virtual XamlValueConverter<XamlDeferringLoader> LookupDeferringLoader ()
                {
                        throw new NotImplementedException ();
@@ -419,25 +608,19 @@ namespace System.Xaml
                        return this.GetCustomAttribute<AmbientAttribute> () != null;
                }
 
+               // It is documented as if it were to reflect spec. section 5.2,
+               // but the actual behavior shows it is *totally* wrong.
+               // Here I have implemented this based on the nunit test results. sigh.
                protected virtual bool LookupIsConstructible ()
                {
-                       // see spec. 5.2.
-                       if (IsArray) // x:Array
-                               return false;
-                       if (type == typeof (XamlType)) // x:XamlType
-                               return false;
-                       // FIXME: handle x:XamlEvent
+                       if (UnderlyingType == null)
+                               return true;
                        if (IsMarkupExtension)
+                               return true;
+                       if (UnderlyingType.IsAbstract)
                                return false;
-                       // FIXME: handle x:Code
-                       // FIXME: commented out.
-                       //if (IsXData)
-                       //      return false;
-
-                       // FIXME: this check is extraneous to spec. 5.2.
-                       if (ConstructionRequiresArguments)
+                       if (!IsNameValid)
                                return false;
-
                        return true;
                }
 
@@ -453,7 +636,7 @@ namespace System.Xaml
 
                protected virtual bool LookupIsNullable ()
                {
-                       return !type.IsValueType || type.ImplementsInterface (typeof (Nullable<>));
+                       return !type.IsValueType || type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>);
                }
 
                protected virtual bool LookupIsPublic ()
@@ -474,15 +657,18 @@ namespace System.Xaml
 
                protected virtual bool LookupIsXData ()
                {
-                       // huh? XamlLanguage.XData.IsXData returns false(!)
-                       // return typeof (XData).IsAssignableFrom (UnderlyingType);
-                       return false;
+                       return CanAssignTo (SchemaContext.GetXamlType (typeof (IXmlSerializable)));
                }
 
                protected virtual XamlType LookupItemType ()
                {
                        if (IsArray)
                                return new XamlType (type.GetElementType (), SchemaContext);
+                       if (IsDictionary) {
+                               if (!IsGeneric)
+                                       return new XamlType (typeof (object), SchemaContext);
+                               return new XamlType (type.GetGenericArguments () [1], SchemaContext);
+                       }
                        if (!IsCollection)
                                return null;
                        if (!IsGeneric)
@@ -507,18 +693,32 @@ namespace System.Xaml
 
                protected virtual XamlMember LookupMember (string name, bool skipReadOnlyCheck)
                {
-                       var pi = UnderlyingType.GetProperty (name);
-                       if (pi != null && (skipReadOnlyCheck || pi.CanWrite))
-                               return new XamlMember (pi, SchemaContext);
-                       var ei = UnderlyingType.GetEvent (name);
-                       if (ei != null)
-                               return new XamlMember (ei, SchemaContext);
-                       return null;
+                       // FIXME: verify if this does not filter out events.
+                       return GetAllMembers ().FirstOrDefault (m => m.Name == name && (skipReadOnlyCheck || !m.IsReadOnly || m.Type.IsCollection || m.Type.IsDictionary || m.Type.IsArray));
                }
 
                protected virtual IList<XamlType> LookupPositionalParameters (int parameterCount)
                {
-                       throw new NotImplementedException ();
+                       if (UnderlyingType == null/* || !IsMarkupExtension*/) // see nunit tests...
+                               return null;
+
+                       // check if there is applicable ConstructorArgumentAttribute.
+                       // If there is, then return its type.
+                       if (parameterCount == 1) {
+                               foreach (var xm in GetAllMembers ()) {
+                                       var ca = xm.GetCustomAttributeProvider ().GetCustomAttribute<ConstructorArgumentAttribute> (false);
+                                       if (ca != null)
+                                               return new XamlType [] {xm.Type};
+                               }
+                       }
+
+                       var methods = (from m in UnderlyingType.GetConstructors (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) where m.GetParameters ().Length == parameterCount select m).ToArray ();
+                       if (methods.Length == 1)
+                               return (from p in methods [0].GetParameters () select SchemaContext.GetXamlType (p.ParameterType)).ToArray ();
+
+                       if (SchemaContext.SupportMarkupExtensionsWithDuplicateArity)
+                               throw new NotSupportedException ("The default LookupPositionalParameters implementation does not allow duplicate arity of markup extensions");
+                       return null;
                }
 
                BindingFlags flags_get_static = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
@@ -552,7 +752,28 @@ namespace System.Xaml
 
                protected virtual XamlValueConverter<TypeConverter> LookupTypeConverter ()
                {
-                       throw new NotImplementedException ();
+                       var t = UnderlyingType;
+                       if (t == null)
+                               return null;
+
+                       // equivalent to TypeExtension.
+                       // FIXME: not sure if it should be specially handled here.
+                       if (t == typeof (Type))
+                               t = typeof (TypeExtension);
+
+                       var a = GetCustomAttributeProvider ();
+                       var ca = a != null ? a.GetCustomAttribute<TypeConverterAttribute> (false) : null;
+                       if (ca != null)
+                               return SchemaContext.GetValueConverter<TypeConverter> (Type.GetType (ca.ConverterTypeName), this);
+
+                       if (t == typeof (object)) // This is a special case. ConverterType is null.
+                               return SchemaContext.GetValueConverter<TypeConverter> (null, this);
+
+                       // It's still not decent to check CollectionConverter.
+                       var tct = t.GetTypeConverter ().GetType ();
+                       if (tct != typeof (TypeConverter) && tct != typeof (CollectionConverter) && tct != typeof (ReferenceConverter))
+                               return SchemaContext.GetValueConverter<TypeConverter> (tct, this);
+                       return null;
                }
 
                protected virtual Type LookupUnderlyingType ()
@@ -566,9 +787,48 @@ namespace System.Xaml
                        return a != null && a.Usable;
                }
 
+               static XamlValueConverter<ValueSerializer> string_value_serializer;
+
                protected virtual XamlValueConverter<ValueSerializer> LookupValueSerializer ()
                {
-                       throw new NotImplementedException ();
+                       return LookupValueSerializer (this, GetCustomAttributeProvider ());
+               }
+
+               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;
+               }
+
+               static string GetXamlName (Type type)
+               {
+                       string n;
+                       if (!type.IsNestedPublic && !type.IsNestedAssembly && !type.IsNestedPrivate)
+                               n = type.Name;
+                       else
+                               n = GetXamlName (type.DeclaringType) + "+" + type.Name;
+                       if (type.IsGenericType && !type.ContainsGenericParameters) // the latter condition is to filter out "nested non-generic type within generic type".
+                               return n.Substring (0, n.IndexOf ('`'));
+                       else
+                               return n;
                }
        }
 }