default(T) on reflected type
In browsing other answers, I have come up with the following extension method which works a treat:
public static T Convert<T>( this string input )
{
var converter = TypeDescriptor.GetConverter( typeof( T ) );
if ( converter != null )
{
try
{
T result = (T) converter.ConvertFromString( input );
return result;
}
catch
{
return default( T );
}
}
return default( T );
}
And I can use it like:
string s = "2011-09-21 17:45";
DateTime result = s.ConvertTo( typeof( DateTime ) );
if ( result == DateTime.MinValue )
doSomethingWithTheBadData();
Awesome! Works great. Now, I'd like to do something similar with a reflected type. I have:
public static dynamic ConvertTo( this string input, Type type )
{
var converter = TypeDescriptor.GetConverter( type );
if ( converter != null )
{
try
{
dynamic result = converter.ConvertFromString( input );
return ( result );
}
catch
{
return default( type ); // bogus
}
}
return default( type ); // bogus
}
And I'd like to use it thus:
Type someType; // will be DateTime, int, et开发者_开发问答c., but not known until runtime
DateTime result = s.ConvertTo( sometype );
if ( result == DateTime.MinValue )
doSomethingWithTheBadData();
Of course, the compiler objects to the 'bogus' lines in the ConvertTo method. What I need (ok, don't necessarily need, but it'd be nice) is a way to get the same result as in the first example so that if the conversion fails, something that can be assigned to the reflected object is returned and can be recognized in the same manner as in the first example.
Edit:
What I finished with:
public static dynamic ConvertTo( this string input, Type type, out bool success )
{
dynamic result;
var converter = TypeDescriptor.GetConverter( type );
if ( converter != null )
{
try
{
result = converter.ConvertFromString( input );
success = true;
return result;
}
catch { /* swallow the exception */ }
}
result = type.IsValueType ? Activator.CreateInstance( type ) : null;
success = false;
return result;
}
and used:
bool success;
string val = "2011-09-21 17:25";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( success )
doSomethingGood();
val = "foo";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( !success )
dealWithBadData();
Remembering that, for the purpose of demonstration, I'm hard-coding the typeof() bit. In my application, the types are all reflected.
Thanks to all for the speedy answers!
You can use
//to get default(T) from an instance of Type
type.IsValueType ? Activator.CreateInstance(type) : null;
This is because value types are guaranteed to have a default constructor, and the default value of a reference type is a null
.
If you're passing in the type using typeof(Type)
, then obviously you could just use the first method. Assuming, then, that you're getting the type via reflection (which you say you are) then you can also use reflection to get the MethodInfo
for your first version of Convert()
, and then use MakeGenericMethod()
to substitute your reflected type into it:
MethodInfo m = typeof(MyConvertExtensions).GetMethod("Convert");
MethodInfo invocable = m.MakeGenericMethod(myReflectedType);
invocable.Invoke(null, new[] { myString });
Untested, but maybe something like this?
public static dynamic ConvertTo(this string input, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
if (converter != null)
{
try
{
return converter.ConvertFromString(input);
}
catch
{
// ignore
}
}
if (type.IsValueType)
return Activator.CreateInstance(type);
return null;
}
精彩评论