I am using 4.0 and I am trying to make my life easy by developing some helper methods for type conversions. Following method is working perfectly. It will convert from any string to other datatype.
System.ComponentModel;
public static T Convert<T>(string s)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
{
return (T)typeConverter.ConvertFrom(s);
}
return default(T);
}
//calling this method...
var dateTime = MyConverter.Convert<DateTime>("13/07/2013"); // Date format "DD/mm/yyyy"
// Working as expected... Taking "13" as Day, "07" as month
Now the following method is also in the same class MyConverter but it is not working well with DateTime:
public static bool CanConvertTo<T>(string s)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
{
return typeConverter.IsValid(s);
}
else
return false;
}
The problem with this method is, it is only accepting dateformat : "MM/dd/yyyy"
// This will give exception. It is taking "13" as month, "07" as Day
bool canConvert = MyConverter.CanConvertTo<DateTime>("13/07/2013");
EDIT As suggested by KeyboardP, I changed my method to :
public static bool CanConvertTo<T>(string s)
{
TypeConverter typeConverter;
if (typeof(T) == typeof(DateTime))
{
typeConverter = new DateTimeConverter();
}
else
{
typeConverter = TypeDescriptor.GetConverter(typeof(T));
}
if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
{
return typeConverter.IsValid(s);
}
else
return false;
}
and tested. Test results are :
var date = MyConverter.Convert<DateTime>("13/07/2013"); //return perfect date
var canConvert = MyConverter.CanConvertTo<DateTime>("13/07/2013"); // returned false...
So no success with DateTimeConverter
Since DateTime
can have many different format styles I'd just use DateTimeConverter than attempt to recreate it inside a generic method.
Edit
I did a bit of ILspying and this is what I've concluded (happy to be corrected on any point).
GetCoverter(typeof(DateTime))
will return a DateTimeConverter
so calling CanConvertFrom
is actually calling DateTimeConverter.CanConvertFrom
. CanConvertFrom
calls base.CanConvertFrom
( base
being the parent TypeConverter class).
The base.CanConvertFrom method looks like this
public virtual bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(InstanceDescriptor);
}
Since DateTime.GetType() != typeof(InstanceDescriptor)
, the return value is false
. CanConvertFrom
is called by the IsValid
method and since we've just established the return value is false
, IsValid
returns false
.
So how comes the Convert
method works even though the same CanConvertFrom
method is called?
Well, the parameter you're passing is of type string
, not DateTime
.
typeConverter.CanConvertFrom(typeof(string))
In the first code snippet above, the CanConvertFrom
method is for the TypeConverter
base class. If we look at DateTimeConverter.CanConvertFrom
override, it looks like this
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
Since we're passing in a String
as the type, this method returns true (unlike the IsValid
call). Because this returns true, the code continues to call
return (T)typeConverter.ConvertFrom(s);
(where T is a DateTime
)
The DateTimeConverter
simply calls DateTime.Parse
and ignores culture. I'm not sure whether this is by design or a bug but I wouldn't rely on DateTime.Parse
unless you know the string is always of the same format (or you format it correctly before calling your method).
DateTimeConverter.IsValid doesn't use current culture. Here's how I got around this
public class FixedDateTimeConverter : DateTimeConverter
{
public override bool IsValid(ITypeDescriptorContext context, object value)
{
DateTime d;
return DateTime.TryParse(value.ToString(), out d);
}
}
...
var converter = TypeDescriptor.GetConverter(typeof (T));
if (typeof (T) == typeof (DateTime))
converter = new FixedDateTimeConverter();
return converter.IsValid(null,r);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.