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;
34 static class TypeExtensionMethods
36 // FIXME: this likely needs to be replaced with XamlTypeName
37 public static string GetXamlName (this Type type)
41 return type.DeclaringType.GetXamlName () + "+" + type.Name;
44 #region inheritance search and custom attribute provision
46 public static T GetCustomAttribute<T> (this ICustomAttributeProvider type, bool inherit) where T : Attribute
48 foreach (var a in type.GetCustomAttributes (typeof (T), inherit))
49 return (T) (object) a;
53 public static T GetCustomAttribute<T> (this XamlType type) where T : Attribute
55 if (type.UnderlyingType == null)
58 T ret = type.CustomAttributeProvider.GetCustomAttribute<T> (true);
61 if (type.BaseType != null)
62 return type.BaseType.GetCustomAttribute<T> ();
66 public static bool ImplementsAnyInterfacesOf (this Type type, params Type [] definitions)
68 return definitions.Any (t => ImplementsInterface (type, t));
71 public static bool ImplementsInterface (this Type type, Type definition)
74 throw new ArgumentNullException ("type");
75 if (definition == null)
76 throw new ArgumentNullException ("definition");
78 foreach (var iface in type.GetInterfaces ())
79 if (iface == definition || (iface.IsGenericType && iface.GetGenericTypeDefinition () == definition))
86 #region type conversion and member value retrieval
88 public static string GetStringValue (this XamlType xt, object obj)
93 // FIXME: DateTimeValueSerializer should apply
94 return (string) TypeDescriptor.GetConverter (typeof (DateTime)).ConvertToInvariantString (obj);
96 return (string) xt.ConvertObject (obj, typeof (string));
99 public static object ConvertObject (this XamlType xt, object target, Type explicitTargetType)
101 return DoConvert (xt.TypeConverter, target, explicitTargetType ?? xt.UnderlyingType);
104 public static object GetMemberValue (this XamlMember xm, XamlType xt, object target)
106 object native = GetPropertyOrFieldValue (xm, xt, target);
107 var memberRType = xm.Type == null ? null : xm.Type.UnderlyingType;
108 return DoConvert (xm.TypeConverter, native, memberRType);
111 static object DoConvert (XamlValueConverter<TypeConverter> converter, object value, Type targetType)
113 // First get member value, then convert it to appropriate target type.
114 var tc = converter != null ? converter.ConverterInstance : null;
115 if (tc != null && targetType != null && tc.CanConvertTo (targetType))
116 return tc.ConvertTo (value, targetType);
120 static object GetPropertyOrFieldValue (this XamlMember xm, XamlType xt, object target)
122 // FIXME: should this be done here??
123 if (xm == XamlLanguage.Initialization)
125 if (xm == XamlLanguage.PositionalParameters) {
126 var argdefs = xt.GetConstructorArguments ().ToArray ();
127 string [] args = new string [argdefs.Length];
128 for (int i = 0; i < args.Length; i++) {
129 var am = argdefs [i];
130 args [i] = GetStringValue (am.Type, GetMemberValue (am, xt, target));
132 return String.Join (", ", args);
135 var mi = xm.UnderlyingMember;
136 var fi = mi as FieldInfo;
138 return fi.GetValue (target);
139 var pi = mi as PropertyInfo;
141 return pi.GetValue (target, null);
143 throw new NotImplementedException (String.Format ("Cannot get value for {0}", xm));
148 public static bool IsContentValue (this XamlMember member)
150 if (member == XamlLanguage.Initialization)
152 if (member == XamlLanguage.PositionalParameters)
154 return IsContentValue (member.Type);
157 public static bool IsContentValue (this XamlType type)
159 var t = type.UnderlyingType;
160 if (Type.GetTypeCode (t) != TypeCode.Object)
162 else if (t == typeof (TimeSpan) || t == typeof (Uri)) // special predefined types
167 public static IEnumerable<XamlMember> GetAllReadWriteMembers (this XamlType type)
169 // FIXME: find out why only TypeExtension yields this directive. Seealso XamlObjectReaderTest
170 if (type == XamlLanguage.Type) {
171 yield return XamlLanguage.PositionalParameters;
175 if (type.IsContentValue ())
176 yield return XamlLanguage.Initialization;
178 foreach (var m in type.GetAllMembers ())
182 public static bool ListEquals (this IList<XamlType> a1, IList<XamlType> a2)
184 if (a1 == null || a1.Count == 0)
185 return a2 == null || a2.Count == 0;
186 if (a2 == null || a2.Count == 0)
188 if (a1.Count != a2.Count)
190 for (int i = 0; i < a1.Count; i++)
191 if (a1 [i] != a2 [i])