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
;
28 using System
.Reflection
;
29 using System
.Windows
.Markup
;
30 using System
.Xaml
.Schema
;
31 using System
.Xml
.Serialization
;
35 public class XamlType
: IEquatable
<XamlType
>
37 public XamlType (Type underlyingType
, XamlSchemaContext schemaContext
)
38 : this (underlyingType
, schemaContext
, null)
42 // static readonly Type [] predefined_types = {
43 // typeof (XData), typeof (Uri), typeof (TimeSpan), typeof (PropertyDefinition), typeof (MemberDefinition), typeof (Reference)
46 public XamlType (Type underlyingType
, XamlSchemaContext schemaContext
, XamlTypeInvoker invoker
)
47 : this (schemaContext
, invoker
)
49 if (underlyingType
== null)
50 throw new ArgumentNullException ("underlyingType");
51 type
= underlyingType
;
52 underlying_type
= type
;
55 if (XamlLanguage
.InitializingTypes
) {
56 // These are special. Only XamlLanguage members are with shorthand name.
57 if (type
== typeof (PropertyDefinition
))
59 else if (type
== typeof (MemberDefinition
))
62 Name
= GetXamlName (type
);
63 PreferredXamlNamespace
= XamlLanguage
.Xaml2006Namespace
;
64 } else if ((xt
= XamlLanguage
.AllTypes
.FirstOrDefault (t
=> t
.UnderlyingType
== type
)) != null) {
66 PreferredXamlNamespace
= XamlLanguage
.Xaml2006Namespace
;
68 Name
= GetXamlName (type
);
69 PreferredXamlNamespace
= String
.Format ("clr-namespace:{0};assembly={1}", type
.Namespace
, type
.Assembly
.GetName ().Name
);
71 if (type
.IsGenericType
) {
72 TypeArguments
= new List
<XamlType
> ();
73 foreach (var gta
in type
.GetGenericArguments ())
74 TypeArguments
.Add (schemaContext
.GetXamlType (gta
));
78 public XamlType (string unknownTypeNamespace
, string unknownTypeName
, IList
<XamlType
> typeArguments
, XamlSchemaContext schemaContext
)
79 : this (schemaContext
, null)
81 if (unknownTypeNamespace
== null)
82 throw new ArgumentNullException ("unknownTypeNamespace");
83 if (unknownTypeName
== null)
84 throw new ArgumentNullException ("unknownTypeName");
85 if (schemaContext
== null)
86 throw new ArgumentNullException ("schemaContext");
88 type
= typeof (object);
89 Name
= unknownTypeName
;
90 PreferredXamlNamespace
= unknownTypeNamespace
;
91 TypeArguments
= typeArguments
!= null && typeArguments
.Count
== 0 ? null : typeArguments
;
92 explicit_ns
= unknownTypeNamespace
;
95 protected XamlType (string typeName
, IList
<XamlType
> typeArguments
, XamlSchemaContext schemaContext
)
96 : this (String
.Empty
, typeName
, typeArguments
, schemaContext
)
100 XamlType (XamlSchemaContext schemaContext
, XamlTypeInvoker invoker
)
102 if (schemaContext
== null)
103 throw new ArgumentNullException ("schemaContext");
104 SchemaContext
= schemaContext
;
105 this.invoker
= invoker
?? new XamlTypeInvoker (this);
108 Type type
, underlying_type
;
112 // populated properties
114 XamlTypeInvoker invoker
;
116 internal EventHandler
<XamlSetMarkupExtensionEventArgs
> SetMarkupExtensionHandler
{
117 get { return LookupSetMarkupExtensionHandler (); }
120 internal EventHandler
<XamlSetTypeConverterEventArgs
> SetTypeConverterHandler
{
121 get { return LookupSetTypeConverterHandler (); }
124 public IList
<XamlType
> AllowedContentTypes
{
125 get { return LookupAllowedContentTypes (); }
128 public XamlType BaseType
{
129 get { return LookupBaseType (); }
132 public bool ConstructionRequiresArguments
{
133 get { return LookupConstructionRequiresArguments (); }
136 public XamlMember ContentProperty
{
137 get { return LookupContentProperty (); }
140 public IList
<XamlType
> ContentWrappers
{
141 get { return LookupContentWrappers (); }
144 public XamlValueConverter
<XamlDeferringLoader
> DeferringLoader
{
145 get { return LookupDeferringLoader (); }
148 public XamlTypeInvoker Invoker
{
149 get { return LookupInvoker (); }
152 public bool IsAmbient
{
153 get { return LookupIsAmbient (); }
156 public bool IsArray
{
157 get { return LookupCollectionKind () == XamlCollectionKind.Array; }
160 // it somehow treats array as not a collection...
161 public bool IsCollection
{
162 get { return LookupCollectionKind () == XamlCollectionKind.Collection; }
165 public bool IsConstructible
{
166 get { return LookupIsConstructible (); }
169 public bool IsDictionary
{
170 get { return LookupCollectionKind () == XamlCollectionKind.Dictionary; }
173 public bool IsGeneric
{
174 get { return type.IsGenericType; }
177 public bool IsMarkupExtension
{
178 get { return LookupIsMarkupExtension (); }
180 public bool IsNameScope
{
181 get { return LookupIsNameScope (); }
183 public bool IsNameValid
{
184 get { return XamlLanguage.IsValidXamlName (Name); }
187 public bool IsNullable
{
188 get { return LookupIsNullable (); }
191 public bool IsPublic
{
192 get { return LookupIsPublic (); }
195 public bool IsUnknown
{
196 get { return LookupIsUnknown (); }
199 public bool IsUsableDuringInitialization
{
200 get { return LookupUsableDuringInitialization (); }
203 public bool IsWhitespaceSignificantCollection
{
204 get { return LookupIsWhitespaceSignificantCollection (); }
207 public bool IsXData
{
208 get { return LookupIsXData (); }
211 public XamlType ItemType
{
212 get { return LookupItemType (); }
215 public XamlType KeyType
{
216 get { return LookupKeyType (); }
219 public XamlType MarkupExtensionReturnType
{
220 get { return LookupMarkupExtensionReturnType (); }
223 public string Name { get; private set; }
225 public string PreferredXamlNamespace { get; private set; }
227 public XamlSchemaContext SchemaContext { get; private set; }
229 public bool TrimSurroundingWhitespace
{
230 get { return LookupTrimSurroundingWhitespace (); }
233 public IList
<XamlType
> TypeArguments { get; private set; }
235 public XamlValueConverter
<TypeConverter
> TypeConverter
{
236 get { return LookupTypeConverter (); }
239 public Type UnderlyingType
{
240 get { return LookupUnderlyingType (); }
243 public XamlValueConverter
<ValueSerializer
> ValueSerializer
{
244 get { return LookupValueSerializer (); }
247 internal string GetInternalXmlName ()
249 if (IsMarkupExtension
&& Name
.EndsWith ("Extension", StringComparison
.Ordinal
))
250 return Name
.Substring (0, Name
.Length
- 9);
251 var stn
= XamlLanguage
.SpecialNames
.FirstOrDefault (s
=> s
.Type
== this);
252 return stn
!= null ? stn
.Name
: Name
;
255 public static bool operator == (XamlType left
, XamlType right
)
257 return IsNull (left
) ? IsNull (right
) : left
.Equals (right
);
260 static bool IsNull (XamlType a
)
262 return Object
.ReferenceEquals (a
, null);
265 public static bool operator != (XamlType left
, XamlType right
)
267 return !(left
== right
);
270 public bool Equals (XamlType other
)
272 // It does not compare XamlSchemaContext.
273 return !IsNull (other
) &&
274 UnderlyingType
== other
.UnderlyingType
&&
275 Name
== other
.Name
&&
276 PreferredXamlNamespace
== other
.PreferredXamlNamespace
&& TypeArguments
.ListEquals (other
.TypeArguments
);
279 public override bool Equals (object obj
)
281 var a
= obj
as XamlType
;
285 public override int GetHashCode ()
287 if (UnderlyingType
!= null)
288 return UnderlyingType
.GetHashCode ();
289 int x
= Name
.GetHashCode () << 7 + PreferredXamlNamespace
.GetHashCode ();
290 if (TypeArguments
!= null)
291 foreach (var t
in TypeArguments
)
292 x
= t
.GetHashCode () + x
<< 5;
296 public override string ToString ()
298 return new XamlTypeName (this).ToString ();
299 //return String.IsNullOrEmpty (PreferredXamlNamespace) ? Name : String.Concat ("{", PreferredXamlNamespace, "}", Name);
302 public virtual bool CanAssignTo (XamlType xamlType
)
304 if (this.UnderlyingType
== null)
305 return xamlType
== XamlLanguage
.Object
;
306 var ut
= xamlType
.UnderlyingType
?? typeof (object);
307 return ut
.IsAssignableFrom (UnderlyingType
);
310 public XamlMember
GetAliasedProperty (XamlDirective directive
)
312 return LookupAliasedProperty (directive
);
315 public ICollection
<XamlMember
> GetAllAttachableMembers ()
317 return new List
<XamlMember
> (LookupAllAttachableMembers ());
320 public ICollection
<XamlMember
> GetAllMembers ()
322 return new List
<XamlMember
> (LookupAllMembers ());
325 public XamlMember
GetAttachableMember (string name
)
327 return LookupAttachableMember (name
);
330 public XamlMember
GetMember (string name
)
332 return LookupMember (name
, true);
335 public IList
<XamlType
> GetPositionalParameters (int parameterCount
)
337 return LookupPositionalParameters (parameterCount
);
340 public virtual IList
<string> GetXamlNamespaces ()
342 throw new NotImplementedException ();
343 /* this does not work like documented!
344 if (explicit_ns != null)
345 return new string [] {explicit_ns};
346 var l = SchemaContext.GetAllXamlNamespaces ();
348 return new List<string> (l);
349 return new string [] {String.Empty};
355 protected virtual XamlMember
LookupAliasedProperty (XamlDirective directive
)
357 if (directive
== XamlLanguage
.Key
) {
358 var a
= this.GetCustomAttribute
<DictionaryKeyPropertyAttribute
> ();
359 return a
!= null ? GetMember (a
.Name
) : null;
361 if (directive
== XamlLanguage
.Name
) {
362 var a
= this.GetCustomAttribute
<RuntimeNamePropertyAttribute
> ();
363 return a
!= null ? GetMember (a
.Name
) : null;
365 if (directive
== XamlLanguage
.Uid
) {
366 var a
= this.GetCustomAttribute
<UidPropertyAttribute
> ();
367 return a
!= null ? GetMember (a
.Name
) : null;
369 if (directive
== XamlLanguage
.Lang
) {
370 var a
= this.GetCustomAttribute
<XmlLangPropertyAttribute
> ();
371 return a
!= null ? GetMember (a
.Name
) : null;
376 protected virtual IEnumerable
<XamlMember
> LookupAllAttachableMembers ()
378 if (UnderlyingType
== null)
379 return BaseType
!= null ? BaseType
.GetAllAttachableMembers () : empty_array
;
380 if (all_attachable_members_cache
== null) {
381 all_attachable_members_cache
= new List
<XamlMember
> (DoLookupAllAttachableMembers ());
382 all_attachable_members_cache
.Sort (TypeExtensionMethods
.CompareMembers
);
384 return all_attachable_members_cache
;
387 IEnumerable
<XamlMember
> DoLookupAllAttachableMembers ()
389 // based on http://msdn.microsoft.com/en-us/library/ff184560.aspx
390 var bf
= BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.Static
;
392 var gl
= new Dictionary
<string,MethodInfo
> ();
393 var sl
= new Dictionary
<string,MethodInfo
> ();
394 var al
= new Dictionary
<string,MethodInfo
> ();
395 //var rl = new Dictionary<string,MethodInfo> ();
396 var nl
= new List
<string> ();
397 foreach (var mi
in UnderlyingType
.GetMethods (bf
)) {
399 if (mi
.Name
.StartsWith ("Get", StringComparison
.Ordinal
)) {
400 if (mi
.ReturnType
== typeof (void))
402 var args
= mi
.GetParameters ();
403 if (args
.Length
!= 1)
405 name
= mi
.Name
.Substring (3);
407 } else if (mi
.Name
.StartsWith ("Set", StringComparison
.Ordinal
)) {
408 // looks like the return type is *ignored*
409 //if (mi.ReturnType != typeof (void))
411 var args
= mi
.GetParameters ();
412 if (args
.Length
!= 2)
414 name
= mi
.Name
.Substring (3);
416 } else if (mi
.Name
.EndsWith ("Handler", StringComparison
.Ordinal
)) {
417 var args
= mi
.GetParameters ();
418 if (args
.Length
!= 2)
420 if (mi
.Name
.StartsWith ("Add", StringComparison
.Ordinal
)) {
421 name
= mi
.Name
.Substring (3, mi
.Name
.Length
- 3 - 7);
423 }/* else if (mi.Name.StartsWith ("Remove", StringComparison.Ordinal)) {
424 name = mi.Name.Substring (6, mi.Name.Length - 6 - 7);
428 if (name
!= null && !nl
.Contains (name
))
432 foreach (var name
in nl
) {
434 var g
= gl
.TryGetValue (name
, out m
) ? m
: null;
435 var s
= sl
.TryGetValue (name
, out m
) ? m
: null;
436 if (g
!= null || s
!= null)
437 yield return new XamlMember (name
, g
, s
, SchemaContext
);
438 var a
= al
.TryGetValue (name
, out m
) ? m
: null;
439 //var r = rl.TryGetValue (name, out m) ? m : null;
441 yield return new XamlMember (name
, a
, SchemaContext
);
445 static readonly XamlMember
[] empty_array
= new XamlMember
[0];
447 protected virtual IEnumerable
<XamlMember
> LookupAllMembers ()
449 if (UnderlyingType
== null)
450 return BaseType
!= null ? BaseType
.GetAllMembers () : empty_array
;
451 if (all_members_cache
== null) {
452 all_members_cache
= new List
<XamlMember
> (DoLookupAllMembers ());
453 all_members_cache
.Sort (TypeExtensionMethods
.CompareMembers
);
455 return all_members_cache
;
458 List
<XamlMember
> all_members_cache
;
459 List
<XamlMember
> all_attachable_members_cache
;
461 IEnumerable
<XamlMember
> DoLookupAllMembers ()
463 // This is a hack that is likely required due to internal implementation difference in System.Uri. Our Uri has two readonly collection properties
464 if (this == XamlLanguage
.Uri
)
467 var bf
= BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.Instance
;
469 foreach (var pi
in UnderlyingType
.GetProperties (bf
))
470 if (pi
.CanRead
&& (pi
.CanWrite
|| IsCollectionType (pi
.PropertyType
) || typeof (IXmlSerializable
).IsAssignableFrom (pi
.PropertyType
)) && pi
.GetIndexParameters ().Length
== 0)
471 yield return new XamlMember (pi
, SchemaContext
);
472 foreach (var ei
in UnderlyingType
.GetEvents (bf
))
473 yield return new XamlMember (ei
, SchemaContext
);
476 static bool IsPublicAccessor (MethodInfo mi
)
478 return mi
!= null && mi
.IsPublic
;
481 bool IsCollectionType (Type type
)
485 var xt
= SchemaContext
.GetXamlType (type
);
486 return xt
.LookupCollectionKind () != XamlCollectionKind
.None
;
489 protected virtual IList
<XamlType
> LookupAllowedContentTypes ()
491 // the actual implementation is very different from what is documented :(
495 var l = new List<XamlType> ();
496 if (ContentWrappers != null)
497 l.AddRange (ContentWrappers);
498 if (ContentProperty != null)
499 l.Add (ContentProperty.Type);
500 if (ItemType != null)
502 return l.Count > 0 ? l : null;
506 protected virtual XamlMember
LookupAttachableMember (string name
)
508 return GetAllAttachableMembers ().FirstOrDefault (m
=> m
.Name
== name
);
512 protected virtual XamlType
LookupBaseType ()
514 if (base_type
== null) {
515 if (UnderlyingType
== null)
516 // FIXME: probably something advanced is needed here.
517 base_type
= new XamlType (typeof (object), SchemaContext
, Invoker
);
519 base_type
= type
.BaseType
== null || type
.BaseType
== typeof (object) ? null : new XamlType (type
.BaseType
, SchemaContext
, Invoker
);
524 // This implementation is not verified. (No place to use.)
525 protected virtual XamlCollectionKind
LookupCollectionKind ()
527 if (UnderlyingType
== null)
528 return BaseType
!= null ? BaseType
.LookupCollectionKind () : XamlCollectionKind
.None
;
530 return XamlCollectionKind
.Array
;
532 if (type
.ImplementsAnyInterfacesOf (typeof (IDictionary
), typeof (IDictionary
<,>)))
533 return XamlCollectionKind
.Dictionary
;
535 if (type
.ImplementsAnyInterfacesOf (typeof (IList
), typeof (ICollection
<>)))
536 return XamlCollectionKind
.Collection
;
538 return XamlCollectionKind
.None
;
541 protected virtual bool LookupConstructionRequiresArguments ()
543 if (UnderlyingType
== null)
546 // not sure if it is required, but MemberDefinition return true while they are abstract and it makes no sense.
547 if (UnderlyingType
.IsAbstract
)
550 // FIXME: probably some primitive types are treated as special.
551 switch (Type
.GetTypeCode (UnderlyingType
)) {
552 case TypeCode
.String
:
554 case TypeCode
.Object
:
555 if (UnderlyingType
== typeof (TimeSpan
))
562 return UnderlyingType
.GetConstructor (BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.Instance
, null, Type
.EmptyTypes
, null) == null;
565 protected virtual XamlMember
LookupContentProperty ()
567 var a
= this.GetCustomAttribute
<ContentPropertyAttribute
> ();
568 return a
!= null && a
.Name
!= null ? GetMember (a
.Name
) : null;
571 protected virtual IList
<XamlType
> LookupContentWrappers ()
573 if (GetCustomAttributeProvider () == null)
576 var arr
= GetCustomAttributeProvider ().GetCustomAttributes (typeof (ContentWrapperAttribute
), false);
577 if (arr
== null || arr
.Length
== 0)
579 var l
= new XamlType
[arr
.Length
];
580 for (int i
= 0; i
< l
.Length
; i
++)
581 l
[i
] = SchemaContext
.GetXamlType (((ContentWrapperAttribute
) arr
[i
]).ContentWrapper
);
585 internal ICustomAttributeProvider
GetCustomAttributeProvider ()
587 return LookupCustomAttributeProvider ();
590 protected internal virtual ICustomAttributeProvider
LookupCustomAttributeProvider ()
592 return UnderlyingType
;
595 protected virtual XamlValueConverter
<XamlDeferringLoader
> LookupDeferringLoader ()
597 throw new NotImplementedException ();
600 protected virtual XamlTypeInvoker
LookupInvoker ()
605 protected virtual bool LookupIsAmbient ()
607 return this.GetCustomAttribute
<AmbientAttribute
> () != null;
610 // It is documented as if it were to reflect spec. section 5.2,
611 // but the actual behavior shows it is *totally* wrong.
612 // Here I have implemented this based on the nunit test results. sigh.
613 protected virtual bool LookupIsConstructible ()
615 if (UnderlyingType
== null)
617 if (IsMarkupExtension
)
619 if (UnderlyingType
.IsAbstract
)
626 protected virtual bool LookupIsMarkupExtension ()
628 return typeof (MarkupExtension
).IsAssignableFrom (UnderlyingType
);
631 protected virtual bool LookupIsNameScope ()
633 return typeof (INameScope
).IsAssignableFrom (UnderlyingType
);
636 protected virtual bool LookupIsNullable ()
638 return !type
.IsValueType
|| type
.ImplementsInterface (typeof (Nullable
<>));
641 protected virtual bool LookupIsPublic ()
643 return underlying_type
== null || underlying_type
.IsPublic
|| underlying_type
.IsNestedPublic
;
646 protected virtual bool LookupIsUnknown ()
648 return UnderlyingType
== null;
651 protected virtual bool LookupIsWhitespaceSignificantCollection ()
653 // probably for unknown types, it should preserve whitespaces.
654 return IsUnknown
|| this.GetCustomAttribute
<WhitespaceSignificantCollectionAttribute
> () != null;
657 protected virtual bool LookupIsXData ()
659 return CanAssignTo (SchemaContext
.GetXamlType (typeof (IXmlSerializable
)));
662 protected virtual XamlType
LookupItemType ()
665 return new XamlType (type
.GetElementType (), SchemaContext
);
668 return new XamlType (typeof (object), SchemaContext
);
669 return new XamlType (type
.GetGenericArguments () [1], SchemaContext
);
674 return new XamlType (typeof (object), SchemaContext
);
675 return new XamlType (type
.GetGenericArguments () [0], SchemaContext
);
678 protected virtual XamlType
LookupKeyType ()
683 return new XamlType (typeof (object), SchemaContext
);
684 return new XamlType (type
.GetGenericArguments () [0], SchemaContext
);
687 protected virtual XamlType
LookupMarkupExtensionReturnType ()
689 var a
= this.GetCustomAttribute
<MarkupExtensionReturnTypeAttribute
> ();
690 return a
!= null ? new XamlType (a
.ReturnType
, SchemaContext
) : null;
693 protected virtual XamlMember
LookupMember (string name
, bool skipReadOnlyCheck
)
695 // FIXME: verify if this does not filter out events.
696 return GetAllMembers ().FirstOrDefault (m
=> m
.Name
== name
&& (skipReadOnlyCheck
|| !m
.IsReadOnly
|| m
.Type
.IsCollection
|| m
.Type
.IsDictionary
|| m
.Type
.IsArray
));
699 protected virtual IList
<XamlType
> LookupPositionalParameters (int parameterCount
)
701 if (UnderlyingType
== null/* || !IsMarkupExtension*/) // see nunit tests...
704 // check if there is applicable ConstructorArgumentAttribute.
705 // If there is, then return its type.
706 if (parameterCount
== 1) {
707 foreach (var xm
in GetAllMembers ()) {
708 var ca
= xm
.GetCustomAttributeProvider ().GetCustomAttribute
<ConstructorArgumentAttribute
> (false);
710 return new XamlType
[] {xm.Type}
;
714 var methods
= (from m
in UnderlyingType
.GetConstructors (BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.Instance
) where m
.GetParameters ().Length
== parameterCount
select m
).ToArray ();
715 if (methods
.Length
== 1)
716 return (from p
in methods
[0].GetParameters () select SchemaContext
.GetXamlType (p
.ParameterType
)).ToArray ();
718 if (SchemaContext
.SupportMarkupExtensionsWithDuplicateArity
)
719 throw new NotSupportedException ("The default LookupPositionalParameters implementation does not allow duplicate arity of markup extensions");
723 BindingFlags flags_get_static
= BindingFlags
.Public
| BindingFlags
.NonPublic
| BindingFlags
.Static
;
725 protected virtual EventHandler
<XamlSetMarkupExtensionEventArgs
> LookupSetMarkupExtensionHandler ()
727 var a
= this.GetCustomAttribute
<XamlSetMarkupExtensionAttribute
> ();
730 var mi
= type
.GetMethod (a
.XamlSetMarkupExtensionHandler
, flags_get_static
);
732 throw new ArgumentException ("Binding to XamlSetMarkupExtensionHandler failed");
733 return (EventHandler
<XamlSetMarkupExtensionEventArgs
>) Delegate
.CreateDelegate (typeof (EventHandler
<XamlSetMarkupExtensionEventArgs
>), mi
);
736 protected virtual EventHandler
<XamlSetTypeConverterEventArgs
> LookupSetTypeConverterHandler ()
738 var a
= this.GetCustomAttribute
<XamlSetTypeConverterAttribute
> ();
741 var mi
= type
.GetMethod (a
.XamlSetTypeConverterHandler
, flags_get_static
);
743 throw new ArgumentException ("Binding to XamlSetTypeConverterHandler failed");
744 return (EventHandler
<XamlSetTypeConverterEventArgs
>) Delegate
.CreateDelegate (typeof (EventHandler
<XamlSetTypeConverterEventArgs
>), mi
);
747 protected virtual bool LookupTrimSurroundingWhitespace ()
749 return this.GetCustomAttribute
<TrimSurroundingWhitespaceAttribute
> () != null;
752 protected virtual XamlValueConverter
<TypeConverter
> LookupTypeConverter ()
754 var t
= UnderlyingType
;
758 // equivalent to TypeExtension.
759 // FIXME: not sure if it should be specially handled here.
760 if (t
== typeof (Type
))
761 t
= typeof (TypeExtension
);
763 var a
= GetCustomAttributeProvider ();
764 var ca
= a
!= null ? a
.GetCustomAttribute
<TypeConverterAttribute
> (false) : null;
766 return SchemaContext
.GetValueConverter
<TypeConverter
> (Type
.GetType (ca
.ConverterTypeName
), this);
768 if (t
== typeof (object)) // This is a special case. ConverterType is null.
769 return SchemaContext
.GetValueConverter
<TypeConverter
> (null, this);
771 // It's still not decent to check CollectionConverter.
772 var tct
= t
.GetTypeConverter ().GetType ();
774 if (tct
!= typeof (TypeConverter
) && tct
.Name
!= "CollectionConverter" && tct
.Name
!= "ReferenceConverter")
776 if (tct
!= typeof (TypeConverter
) && tct
!= typeof (CollectionConverter
) && tct
!= typeof (ReferenceConverter
))
778 return SchemaContext
.GetValueConverter
<TypeConverter
> (tct
, this);
782 protected virtual Type
LookupUnderlyingType ()
784 return underlying_type
;
787 protected virtual bool LookupUsableDuringInitialization ()
789 var a
= this.GetCustomAttribute
<UsableDuringInitializationAttribute
> ();
790 return a
!= null && a
.Usable
;
793 static XamlValueConverter
<ValueSerializer
> string_value_serializer
;
795 protected virtual XamlValueConverter
<ValueSerializer
> LookupValueSerializer ()
797 return LookupValueSerializer (this, GetCustomAttributeProvider ());
800 internal static XamlValueConverter
<ValueSerializer
> LookupValueSerializer (XamlType targetType
, ICustomAttributeProvider provider
)
802 if (provider
== null)
805 var a
= provider
.GetCustomAttribute
<ValueSerializerAttribute
> (true);
807 return new XamlValueConverter
<ValueSerializer
> (a
.ValueSerializerType
?? Type
.GetType (a
.ValueSerializerTypeName
), targetType
);
809 if (targetType
.BaseType
!= null) {
810 var ret
= targetType
.BaseType
.LookupValueSerializer ();
815 if (targetType
.UnderlyingType
== typeof (string)) {
816 if (string_value_serializer
== null)
817 string_value_serializer
= new XamlValueConverter
<ValueSerializer
> (typeof (StringValueSerializer
), targetType
);
818 return string_value_serializer
;
824 static string GetXamlName (Type type
)
827 if (!type
.IsNestedPublic
&& !type
.IsNestedAssembly
&& !type
.IsNestedPrivate
)
830 n
= GetXamlName (type
.DeclaringType
) + "+" + type
.Name
;
831 if (type
.IsGenericType
&& !type
.ContainsGenericParameters
) // the latter condition is to filter out "nested non-generic type within generic type".
832 return n
.Substring (0, n
.IndexOf ('`'));