I'm having an ussue with the TypeDescriptor class.
I have a cookie which contains a date - the date is converted to a string and then back again using some helper methods.
One of my staple extension methods is used to do the conversion, however it throws a forced error because the date is not convertible back from a string.
Here's the message I output:
22/01/2015 14:29:15 could not be converted to DateTime
Looks like a DateTime to me!
The problem can be overcome by using Convert.ToDateTime()
, so the code in general is ok. i also use it for dates elwhere with no problems to date.
The only difference is that I'm converting in the middle of a linq statement like this:
Set = new SortedSet<TrackedItem>(set
.Split(';')
.Select(s =>
{
var parts = s.Split(',');
return new TrackedItem(
parts[0].ConvertTo<int>(),
Convert.ToDateTime(parts[1]));
}));
Any ideas?
public static T ConvertTo<T>(this object obj, bool throwInvalid = false)
where T : IConvertible
{
// Object does not require converting.
if (obj is T) return (T)obj;
// Determine if object can be converted.
var type = typeof(T);
var converter = TypeDescriptor.GetConverter(type);
var isConvertible = converter != null && converter.IsValid(obj);
var error = string.Format("'{0}' could not be converted to type {1}", obj, type.Name);
// If no conversion is available, and defaults not allowed throw an error.
(!isConvertible && throwInvalid).ThrowTrue(error);
// If the object is convertible, convert it, else return the default(T).
return isConvertible ? (T)converter.ConvertFrom(obj) : default(T);
}
I'm guessing from your date example that you're running in the en-GB
culture. Unfortunately, to draw liberally from this related q/a, IsValid
always uses CultureInfo.InvariantCulture
(US date format) to decide its answer. So when running in en-GB
with a date such as your example, IsValid
will return false
; but ConvertFrom
, which by default uses the current thread culture will succeed!
Interestingly, the latest docs for IsValid
massively hedge the question of whether this is actually a bug:
The
IsValid
method is used to validate a value within the type rather than to determine if value can be converted to the given type. For example,IsValid
can be used to determine if a given value is valid for an enumeration type.
So really you shouldn't be using IsValid
here at all - you should be doing what the same docs go on to suggest:
You can write your own
WillConvertSucceed
method by wrapping theConvertTo
andConvertFrom
methods in exception blocks.
And in that method you can be sure to use the CultureInfo
you actually care about.