In my program, i'm reading SchemData from a table. I need to determine the column size and decide at runtime if a given value matches the column size and could be written to that column. In case of alpha-numeric Types like char, nvarchar,... this is no problem.
But in case of numeric values i cannot compare the value with the column size, because column size will give me the amount of bytes to store inside that column, if my understanding here is correct.
So i want to check, if my numeric values are inside the MaxValue range of that particular data type stored inside a System.Type variable of that column.
I started with determining the MaxValue using reflection and also recognizing nullable types like that:
public static Object GetMaxValue(this Type type)
{
var t = GetNullableType(type);
var f = t.GetField("MaxValue");
if (f == null)
return null;
else
return f.GetValue(null);
}
public static Type GetNullableType(Type type)
{
Type retType = type;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
var nullableConverter = new System.ComponentModel.NullableConverter(type);
retType = nullableConverter.UnderlyingType;
}
return retType;
}
Now i get an object, storing the MaxValue information.
How can i compare the MaxValue stored inside an object with another value, stored inside another object (or maybe a string). The value inside the second object (or string, as mentioned before) are read from a xml file, therefor this is not a specific type like int. It needs to be from type object.
The only thing to solve the comparison thing i thought of was implementing a method and checking for every single numeric type inside a switch and performing a try parse and return true/false.
First example method looks like this:
public static bool TestMaxValue(this Type type, object compare)
{
var t = GetNullableType(type);
var mv = t.GetMaxValue();
bool ret = false;
switch (Type.GetTypeCode(t))
{
case TypeCode.Byte:
{
Byte b;
if (Byte.TryParse(compare.ToString(), out b))
ret =(Convert.ToByte(mv) >= b);
break;
}
case TypeCode.Decimal:
{
Decimal b;
if (Decimal.TryParse(compare.ToString(), out b))
ret = (Convert.ToDecimal(mv) >= b);
break;
}
case TypeCode.Double:
{
Double b;
if (Double.TryParse(compare.ToString(), out b))
ret = (Convert.ToDouble(mv) >= b);
break;
}
case TypeCode.Int16:
{
Int16 b;
if (Int16.TryParse(compare.ToString(), out b))
ret = (Convert.ToInt16(mv) >= b);
break;
}
case TypeCode.Int32:
{
Int32 b;
if (Int32.TryParse(compare.ToString(), out b))
ret = (Convert.ToInt32(mv) >= b);
break;
}
}
return ret;
}
Does anyone have a better idea than implementing such a method? Thanks in advance.
You can use Convert.ChangeType and IComparable to solve this. All primitive types are inherited from IComparable. This snippet is working at my end. Make sure u catch the exception inside or outside as ChangeType throws format exception if the conversion type is incorrect.
public static bool TestMaxValue(this Type type, object compare)
{
var t = GetNullableType(type);
var mv = t.GetMaxValue();
bool ret = false;
try
{
IComparable maxValue = Convert.ChangeType(mv, t) as IComparable;
IComparable currentValue = Convert.ChangeType(compare, t) as IComparable;
if (maxValue != null && currentValue != null)
ret = maxValue.CompareTo(currentValue) > 0;
}
catch (FormatException exception)
{
//handle is here
ret = false;
}
return ret;
}
Although its recommended to not write extension methods as it reduces type safety. Create extension methods for specific types separately like
public static bool TestMaxValue(this int? value, int compareValue)
{
var intValue = value.GetValueOrDefault();
var ret = intValue.CompareTo(compareValue) > 0;
return ret;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With