Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / class / System.Core / System.Linq.Expressions / Extensions.cs
index 8773382aaf936bdd6e9cd068042d610ae1b67d1e..0f4eadfd3428136e3ac4df8660c88a9f3a9d6967 100644 (file)
 //
 
 using System;
+using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
 
 namespace System.Linq.Expressions {
 
        static class Extensions {
 
+               public static bool IsGenericInstanceOf (this Type self, Type type)
+               {
+                       if (!self.IsGenericType)
+                               return false;
+
+                       return self.GetGenericTypeDefinition () == type;
+               }
+
+               public static bool IsNullable (this Type self)
+               {
+                       return self.IsValueType && self.IsGenericInstanceOf (typeof (Nullable<>));
+               }
+
+               public static bool IsExpression (this Type self)
+               {
+                       return self == typeof (Expression) || self.IsSubclassOf (typeof (Expression));
+               }
+
+               public static bool IsGenericImplementationOf (this Type self, Type type, out Type generic_iface)
+               {
+                       foreach (var iface in self.GetInterfaces ()) {
+                               if (!iface.IsGenericInstanceOf (type))
+                                       continue;
+
+                               generic_iface = iface;
+                               return true;
+                       }
+
+                       generic_iface = null;
+                       return false;
+               }
+
                public static bool IsAssignableTo (this Type self, Type type)
                {
-                       return type.IsAssignableFrom (self);
+                       return type.IsAssignableFrom (self)
+                               || ArrayTypeAreAssignable (self, type)
+                               || ArrayTypeIsAssignableToInterface (self, type);               
+               }
+
+               public static Type GetFirstGenericArgument (this Type self)
+               {
+                       return self.GetGenericArguments () [0];
+               }
+
+               public static Type MakeGenericTypeFrom (this Type self, Type type)
+               {
+                       return self.MakeGenericType (type.GetGenericArguments ());
+               }
+
+               public static Type MakeNullableType (this Type self)
+               {
+                       return typeof (Nullable<>).MakeGenericType (self);
+               }
+
+               public static Type GetNotNullableType (this Type self)
+               {
+                       return self.IsNullable () ? self.GetFirstGenericArgument () : self;
+               }
+
+               public static MethodInfo GetInvokeMethod (this Type self)
+               {
+                       return self.GetMethod ("Invoke", BindingFlags.Public | BindingFlags.Instance);
+               }
+
+               public static MethodInfo MakeGenericMethodFrom (this MethodInfo self, MethodInfo method)
+               {
+                       return self.MakeGenericMethod (method.GetGenericArguments ());
                }
-/*
+
+               public static Type [] GetParameterTypes (this MethodBase self)
+               {
+                       var parameters = self.GetParameters ();
+                       var types = new Type [parameters.Length];
+
+                       for (int i = 0; i < types.Length; i++)
+                               types [i] = parameters [i].ParameterType;
+
+                       return types;
+               }
+
+               static bool ArrayTypeAreAssignable (Type type, Type candidate)
+               {
+                       if (!type.IsArray || !candidate.IsArray)
+                               return false;
+
+                       if (type.GetArrayRank () != candidate.GetArrayRank ())
+                               return false;
+
+                       return type.GetElementType ().IsAssignableTo (candidate.GetElementType ());
+               }
+
+               static bool ArrayTypeIsAssignableToInterface (Type type, Type candidate)
+               {
+                       if (!type.IsArray)
+                               return false;
+
+                       if (!(candidate.IsGenericInstanceOf (typeof (IList<>)) || candidate.IsGenericInstanceOf (typeof (ICollection<>)) || candidate.IsGenericInstanceOf (typeof (IEnumerable<>))))
+                               return false;
+
+                       return type.GetElementType () == candidate.GetFirstGenericArgument ();
+               }
+
                public static void OnFieldOrProperty (this MemberInfo self,
                        Action<FieldInfo> onfield, Action<PropertyInfo> onprop)
                {
@@ -53,7 +152,7 @@ namespace System.Linq.Expressions {
                                throw new ArgumentException ();
                        }
                }
-*/
+
                public static T OnFieldOrProperty<T> (this MemberInfo self,
                        Func<FieldInfo, T> onfield, Func<PropertyInfo, T> onprop)
                {
@@ -66,5 +165,10 @@ namespace System.Linq.Expressions {
                                throw new ArgumentException ();
                        }
                }
+
+               public static Type MakeStrongBoxType (this Type self)
+               {
+                       return typeof (StrongBox<>).MakeGenericType (self);
+               }
        }
 }