Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
TypeExtensions.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Linq;
5 using System.Reflection;
6 using System.Runtime.CompilerServices;
7 
8 namespace SiliconStudio.Core.Reflection
9 {
10  public static class TypeExtensions
11  {
12  public static bool HasInterface(this Type type, Type lookInterfaceType)
13  {
14  return type.GetInterface(lookInterfaceType) != null;
15  }
16 
17  public static Type GetInterface(this Type type, Type lookInterfaceType)
18  {
19  if (type == null)
20  throw new ArgumentNullException("type");
21  if (lookInterfaceType == null)
22  throw new ArgumentNullException("lookInterfaceType");
23 
24  var typeinfo = lookInterfaceType.GetTypeInfo();
25  if (typeinfo .IsGenericTypeDefinition)
26  {
27  if (typeinfo.IsInterface)
28  foreach (var interfaceType in type.GetTypeInfo().ImplementedInterfaces)
29  if (interfaceType.GetTypeInfo().IsGenericType
30  && interfaceType.GetGenericTypeDefinition() == lookInterfaceType)
31  return interfaceType;
32 
33  for (Type t = type; t != null; t = t.GetTypeInfo().BaseType)
34  if (t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == lookInterfaceType)
35  return t;
36  }
37  else
38  {
39  if (lookInterfaceType.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
40  return lookInterfaceType;
41  }
42 
43  return null;
44  }
45 
46  /// <summary>
47  /// Gets the assembly qualified name of the type, but without the assembly version or public token.
48  /// </summary>
49  /// <param name="type">The type.</param>
50  /// <returns>The assembly qualified name of the type, but without the assembly version or public token.</returns>
51  /// <exception cref="System.InvalidOperationException">Unable to get an assembly qualified name for type [{0}].DoFormat(type)</exception>
52  internal static string GetShortAssemblyQualifiedName(this Type type)
53  {
54  var typeName = type.AssemblyQualifiedName;
55  if (typeName == null)
56  {
57  throw new InvalidOperationException("Unable to get an assembly qualified name for type [{0}]".ToFormat(type));
58  }
59 
60  var indexAfterType = typeName.IndexOf(',');
61  if (indexAfterType >= 0)
62  {
63  var indexAfterAssembly = typeName.IndexOf(',', indexAfterType + 1);
64  if (indexAfterAssembly >= 0)
65  {
66  typeName = typeName.Substring(0, indexAfterAssembly).Replace(" ", string.Empty);
67  }
68  }
69  return typeName;
70  }
71 
72  /// <summary>
73  /// Compare two objects to see if they are equal or not. Null is acceptable.
74  /// </summary>
75  /// <param name="a"></param>
76  /// <param name="b"></param>
77  /// <returns></returns>
78  public static bool AreEqual(object a, object b)
79  {
80  if (a == null)
81  return b == null;
82  if (b == null)
83  return false;
84  return a.Equals(b) || b.Equals(a);
85  }
86 
87  /// <summary>
88  /// Determines whether the specified type is an anonymous type.
89  /// </summary>
90  /// <param name="type">The type.</param>
91  /// <returns><c>true</c> if the specified type is anonymous; otherwise, <c>false</c>.</returns>
92  public static bool IsAnonymous(this Type type)
93  {
94  if (type == null)
95  return false;
96 
97  return type.GetTypeInfo().GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any()
98  && type.Namespace == null
99  && type.FullName.Contains("AnonymousType");
100  }
101 
102  /// <summary>
103  /// Determines whether the specified type is nullable <see cref="Nullable{T}"/>.
104  /// </summary>
105  /// <param name="type">The type.</param>
106  /// <returns><c>true</c> if the specified type is nullable; otherwise, <c>false</c>.</returns>
107  public static bool IsNullable(this Type type)
108  {
109  return Nullable.GetUnderlyingType(type) != null;
110  }
111 
112  /// <summary>
113  /// Check if the type is a ValueType and does not contain any non ValueType members.
114  /// </summary>
115  /// <param name="type"></param>
116  /// <returns></returns>
117  public static bool IsPureValueType(this Type type)
118  {
119  if (type == null)
120  return false;
121  if (type == typeof(IntPtr))
122  return false;
123  if (type.GetTypeInfo().IsPrimitive)
124  return true;
125  if (type.GetTypeInfo().IsEnum)
126  return true;
127  if (!type.GetTypeInfo().IsValueType)
128  return false;
129  // struct
130  return type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).All(f => IsPureValueType(f.FieldType));
131  }
132 
133  /// <summary>
134  /// Returnes true if the specified <paramref name="type"/> is a struct type.
135  /// </summary>
136  /// <param name="type"><see cref="Type"/> to be analyzed.</param>
137  /// <returns>true if the specified <paramref name="type"/> is a struct type; otehrwise false.</returns>
138  public static bool IsStruct(this Type type)
139  {
140  return type != null && type.GetTypeInfo().IsValueType && !type.GetTypeInfo().IsPrimitive && !type.GetTypeInfo().IsEnum;
141  }
142 
143  /// <summary>
144  /// Indicates whether the given type represents a numeric value.
145  /// </summary>
146  /// <param name="type">The type.</param>
147  /// <returns>True if object is a numeric value.</returns>
148  public static bool IsNumeric(this Type type)
149  {
150  return type != null && (type == typeof(sbyte) || type == typeof(short) || type == typeof(int) || type == typeof(long) ||
151  type == typeof(byte) || type == typeof(ushort) || type == typeof(uint) || type == typeof(ulong) ||
152  type == typeof(float) || type == typeof(double) || type == typeof(decimal));
153  }
154 
155  /// <summary>
156  /// Gets the minimum value for the given numeric type.
157  /// </summary>
158  /// <param name="type">The type for which to get the minimum value.</param>
159  /// <returns>The minimum value of the given type.</returns>
160  /// <exception cref="ArgumentException">The given type is not a numeric type.</exception>
161  /// <remarks>A type is numeric when <see cref="IsNumeric"/> returns true.</remarks>
162  public static object GetMinimum(this Type type)
163  {
164  if (type == typeof(sbyte))
165  return sbyte.MinValue;
166  if (type == typeof(short))
167  return short.MinValue;
168  if (type == typeof(int))
169  return int.MinValue;
170  if (type == typeof(long))
171  return long.MinValue;
172  if (type == typeof(byte))
173  return byte.MinValue;
174  if (type == typeof(ushort))
175  return ushort.MinValue;
176  if (type == typeof(uint))
177  return uint.MinValue;
178  if (type == typeof(ulong))
179  return ulong.MinValue;
180  if (type == typeof(float))
181  return float.MinValue;
182  if (type == typeof(double))
183  return double.MinValue;
184  if (type == typeof(decimal))
185  return decimal.MinValue;
186 
187  throw new ArgumentException("Numeric type expected");
188  }
189 
190  /// <summary>
191  /// Gets the maximum value for the given numeric type.
192  /// </summary>
193  /// <param name="type">The type for which to get the maximum value.</param>
194  /// <returns>The maximum value of the given type.</returns>
195  /// <exception cref="ArgumentException">The given type is not a numeric type.</exception>
196  /// <remarks>A type is numeric when <see cref="IsNumeric"/> returns true.</remarks>
197  public static object GetMaximum(this Type type)
198  {
199  if (type == typeof(sbyte))
200  return sbyte.MaxValue;
201  if (type == typeof(short))
202  return short.MaxValue;
203  if (type == typeof(int))
204  return int.MaxValue;
205  if (type == typeof(long))
206  return long.MaxValue;
207  if (type == typeof(byte))
208  return byte.MaxValue;
209  if (type == typeof(ushort))
210  return ushort.MaxValue;
211  if (type == typeof(uint))
212  return uint.MaxValue;
213  if (type == typeof(ulong))
214  return ulong.MaxValue;
215  if (type == typeof(float))
216  return float.MaxValue;
217  if (type == typeof(double))
218  return double.MaxValue;
219  if (type == typeof(decimal))
220  return decimal.MaxValue;
221 
222  throw new ArgumentException("Numeric type expected");
223  }
224 
225  /// <summary>
226  /// Cast an object to a specified numeric type.
227  /// </summary>
228  /// <param name="obj">Any object</param>
229  /// <param name="type">Numric type</param>
230  /// <returns>Numeric value or null if the object is not a numeric value.</returns>
231  public static object CastToNumericType(this Type type, object obj)
232  {
233  var doubleValue = CastToDouble(obj);
234  if (double.IsNaN(doubleValue))
235  return null;
236 
237  if (obj is decimal && type == typeof(decimal))
238  return obj; // do not convert into double
239 
240  object result = null;
241  if (type == typeof(sbyte))
242  result = (sbyte)doubleValue;
243  if (type == typeof(byte))
244  result = (byte)doubleValue;
245  if (type == typeof(short))
246  result = (short)doubleValue;
247  if (type == typeof(ushort))
248  result = (ushort)doubleValue;
249  if (type == typeof(int))
250  result = (int)doubleValue;
251  if (type == typeof(uint))
252  result = (uint)doubleValue;
253  if (type == typeof(long))
254  result = (long)doubleValue;
255  if (type == typeof(ulong))
256  result = (ulong)doubleValue;
257  if (type == typeof(float))
258  result = (float)doubleValue;
259  if (type == typeof(double))
260  result = doubleValue;
261  if (type == typeof(decimal))
262  result = (decimal)doubleValue;
263  return result;
264  }
265 
266  /// <summary>
267  /// Cast boxed numeric value to double
268  /// </summary>
269  /// <param name="obj">boxed numeric value</param>
270  /// <returns>Numeric value in double. Double.Nan if obj is not a numeric value.</returns>
271  internal static double CastToDouble(object obj)
272  {
273  var result = double.NaN;
274  var type = obj != null ? obj.GetType() : null;
275  if (type == typeof(sbyte))
276  result = (sbyte)obj;
277  if (type == typeof(byte))
278  result = (byte)obj;
279  if (type == typeof(short))
280  result = (short)obj;
281  if (type == typeof(ushort))
282  result = (ushort)obj;
283  if (type == typeof(int))
284  result = (int)obj;
285  if (type == typeof(uint))
286  result = (uint)obj;
287  if (type == typeof(long))
288  result = (long)obj;
289  if (type == typeof(ulong))
290  result = (ulong)obj;
291  if (type == typeof(float))
292  result = (float)obj;
293  if (type == typeof(double))
294  result = (double)obj;
295  if (type == typeof(decimal))
296  result = (double)(decimal)obj;
297  return result;
298  }
299  }
300 }
static bool AreEqual(object a, object b)
Compare two objects to see if they are equal or not. Null is acceptable.
function b
static bool IsAnonymous(this Type type)
Determines whether the specified type is an anonymous type.
function a
static object GetMinimum(this Type type)
Gets the minimum value for the given numeric type.
static bool IsNumeric(this Type type)
Indicates whether the given type represents a numeric value.
static bool IsStruct(this Type type)
Returnes true if the specified type is a struct type.
Let the emitter choose the style.
static object GetMaximum(this Type type)
Gets the maximum value for the given numeric type.
static object CastToNumericType(this Type type, object obj)
Cast an object to a specified numeric type.
static Type GetInterface(this Type type, Type lookInterfaceType)
static bool HasInterface(this Type type, Type lookInterfaceType)
static bool IsPureValueType(this Type type)
Check if the type is a ValueType and does not contain any non ValueType members.
static bool IsNullable(this Type type)
Determines whether the specified type is nullable Nullable{T}.