using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
namespace System.Linq.Expressions
{
static class ExpressionUtil
{
private static TypeCode GetTypeCode(Type type)
{
if (Expression.IsNullableType(type))
type = Expression.GetNonNullableType(type);
return Type.GetTypeCode(type);
}
private static bool IsNumber(TypeCode typeCode)
{
if (IsInteger(typeCode) ||
typeCode == TypeCode.Single ||
typeCode == TypeCode.Double ||
typeCode == TypeCode.Decimal)
return true;
return false;
}
private static bool IsInteger(TypeCode typeCode)
{
if (typeCode == TypeCode.Byte ||
typeCode == TypeCode.SByte ||
typeCode == TypeCode.Int16 ||
typeCode == TypeCode.UInt16 ||
typeCode == TypeCode.Int32 ||
typeCode == TypeCode.UInt32 ||
typeCode == TypeCode.Int64 ||
typeCode == TypeCode.UInt64)
return true;
return false;
}
public static bool IsNumber(Type type)
{
// fast exit: enum is not numeric
if (type.IsEnum)
return false;
return IsNumber(GetTypeCode(type));
}
public static bool IsInteger(Type type)
{
// fast exit: enum is not numeric
if (type.IsEnum)
return false;
return IsInteger(GetTypeCode(type));
}
public static bool IsNumber(object value)
{
if (value == null)
return false;
return IsNumber(value.GetType());
}
public static bool IsInteger(object value)
{
if (value == null)
return false;
return IsInteger(value.GetType());
}
///
/// tries to find the method with the given name in one of the
/// given types in the array.
///
/// The name of the method to find.
/// An array of (typically 2) defining
/// the types we're going to check for the method.
///
public static MethodInfo GetMethod(string methodName, Type[] types)
{
if (types.Length > 2)
throw new ArgumentException();
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
// the method should have the two types defined as argument...
MethodInfo method = types[0].GetMethod(methodName, flags, null, types, null);
if (method == null && types.Length > 1)
method = types[1].GetMethod(methodName, flags, null, types, null);
return method;
}
public static MethodInfo GetOperatorMethod(string methodName, Type left, Type right)
{
MethodInfo opMethod = GetMethod(methodName, new Type[] { left, right });
if (opMethod == null)
{
if (Expression.IsNullableType(left) &&
Expression.IsNullableType(right))
{
// they're nullable types: try to refine them and get the method again...
left = Expression.GetNonNullableType(left);
right = Expression.GetNonNullableType(right);
opMethod = GetMethod(methodName, new Type[] { left, right });
}
// hope at this point we've found it...
return opMethod;
}
if (!opMethod.IsStatic)
throw new ArgumentException();
if (opMethod.ReturnType == typeof(void))
throw new ArgumentException();
ParameterInfo[] pars = opMethod.GetParameters();
if (pars.Length != 2)
throw new ArgumentException();
ParameterInfo p1 = pars[0];
ParameterInfo p2 = pars[1];
if (p1.ParameterType.IsAssignableFrom(left))
throw new ArgumentException();
if (p2.ParameterType.IsAssignableFrom (right))
throw new ArgumentException();
// check for the nullability of the types...
if (Expression.IsNullableType(p1.ParameterType) &&
!Expression.IsNullableType(left))
throw new InvalidOperationException();
if (Expression.IsNullableType(p2.ParameterType) &&
!Expression.IsNullableType(right))
throw new InvalidOperationException();
return opMethod;
}
public static Type GetNullable(Type type)
{
if (Expression.IsNullableType(type))
return type;
return typeof(Nullable<>).MakeGenericType(type);
}
}
}