Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / class / System.Core / System.Linq.Expressions / Extensions.cs
index 612ba94cb5ab966bb84fae9d5f1b2253ff2d483c..0f4eadfd3428136e3ac4df8660c88a9f3a9d6967 100644 (file)
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection.Emit;
 using System.Runtime.CompilerServices;
@@ -45,21 +46,33 @@ namespace System.Linq.Expressions {
 
                public static bool IsNullable (this Type self)
                {
-                       return self.IsGenericInstanceOf (typeof (Nullable<>));
+                       return self.IsValueType && self.IsGenericInstanceOf (typeof (Nullable<>));
                }
 
-               public static bool IsGenericImplementationOf (this Type self, Type type)
+               public static bool IsExpression (this Type self)
                {
-                       foreach (Type iface in self.GetInterfaces ())
-                               if (iface.IsGenericInstanceOf (type))
-                                       return true;
+                       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) ||
-                               ArrayTypeIsAssignableTo (self, type);
+                       return type.IsAssignableFrom (self)
+                               || ArrayTypeAreAssignable (self, type)
+                               || ArrayTypeIsAssignableToInterface (self, type);               
                }
 
                public static Type GetFirstGenericArgument (this Type self)
@@ -77,6 +90,16 @@ namespace System.Linq.Expressions {
                        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 ());
@@ -93,7 +116,7 @@ namespace System.Linq.Expressions {
                        return types;
                }
 
-               static bool ArrayTypeIsAssignableTo (Type type, Type candidate)
+               static bool ArrayTypeAreAssignable (Type type, Type candidate)
                {
                        if (!type.IsArray || !candidate.IsArray)
                                return false;
@@ -104,6 +127,17 @@ namespace System.Linq.Expressions {
                        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)
                {