How to lookup and invoke a .Net TypeConverter for a particular type?
Solution 1
TypeConverter converter = TypeDescriptor.GetConverter(sourceType);
if(converter.CanConvertTo(destinationType)) {
return converter.ConvertTo(obj, destinationType);
}
converter = TypeDescriptor.GetConverter(destinationType);
if(converter.CanConvertFrom(sourceType)) {
return converter.ConvertFrom(obj);
}
You could also look at Convert.ChangeType(obj, destinationType)
Solution 2
Here's the code used in one of our existing apps... not sure if it's ideal but it works well for us.
/// <summary>
/// Attempts to convert a value using any customer TypeConverters applied to the member
/// </summary>
/// <param name="value">Object containing the value to be assigned</param>
/// <param name="member">Member to be assigned to</param>
/// <returns><paramref name="value"/> converted to the appropriate type</returns>
public static Object CustomTypeConversion ( object value, MemberInfo member )
{
if ( value == null || value == DBNull.Value )
return value;
if ( member == null )
throw new ArgumentNullException ( );
List<TypeConverter> converters = GetCustomTypeConverters ( member );
foreach ( TypeConverter c in converters )
{
if ( c.CanConvertFrom ( value.GetType ( ) ) )
return c.ConvertFrom ( value );
}
if ( member is PropertyInfo )
{
PropertyInfo prop = member as PropertyInfo;
return ConvertToNative( value , prop.PropertyType );
}
return ConvertToNative ( value, member.MemberType.GetType ( ) );
}
/// <summary>
/// Extracts and instantiates any customer type converters assigned to a
/// derivitive of the <see cref="System.Reflection.MemberInfo"/> property
/// </summary>
/// <param name="member">Any class deriving from MemberInfo</param>
/// <returns>A list of customer type converters, empty if none found</returns>
public static List<TypeConverter> GetCustomTypeConverters ( System.Reflection.MemberInfo member )
{
List<TypeConverter> result = new List<TypeConverter>();
try
{
foreach ( TypeConverterAttribute a in member.GetCustomAttributes( typeof( TypeConverterAttribute ) , true ) )
{
TypeConverter converter = Activator.CreateInstance( Type.GetType( a.ConverterTypeName ) ) as TypeConverter;
if ( converter != null )
result.Add( converter );
}
}
catch
{
// Let it go, there were no custom converters
}
return result;
}
/// <summary>
/// Attempts to cast the incoming database field to the property type
/// </summary>
/// <param name="value">Database value to cast</param>
/// <param name="castTo">Type to cast to</param>
/// <returns>The converted value, if conversion failed the original value will be returned</returns>
public static object ConvertToNative ( object value , Type castTo )
{
try
{
return Convert.ChangeType( value , castTo , System.Threading.Thread.CurrentThread.CurrentCulture );
}
catch
{
return value;
}
}
Just call the CustomTypeConversion method and away you go... probably a little more than you need but being thorough isn't a crime (or is it?).
Solution 3
I don't know how robust it is, but I sometimes use this code for generic type conversion :
public T ConvertTo<T>(object value)
{
return (T)Convert.ChangeType(value, typeof(T));
}
I don't know if the ChangeType method use TypeConverters...
Solution 4
In addition to Marc's answer, you might consider that ASP.NET's ViewState does a similar function to what you're asking to do. It tries to find the most efficient conversion.
It might be worth a look at this page and possibly this one too.
romu
I'm writing a new book: Rapid Fullstack Development. Learn from my years of experience and become a better developer. My second book, Bootstrapping Microservices, is a practical and project-based guide to building distributed applications with microservices. My first book Data Wrangling with JavaScript is a comprehensive overview of working with data in JavaScript. Data-Forge Notebook is my notebook-style application for data transformation, analysis and transformation in JavaScript. I have a long history in software development with many years in apps, web apps, backends, serious games, simulations and VR. Making technology work for business is what I do: building bespoke software solutions that span multiple platforms. I have years of experience managing development teams, preparing technical strategies and creation of software products. I can explain complicated technology to senior management. I have delivered cutting-edge products in fast-paced and high-pressure environments. I know how to focus and prioritize to get the important things done. Author Rapid Fullstack Development Bootstrapping Microservices Data Wrangling with JavaScript Creator of Market Wizard https://www.market-wizard.com.au/ Creator of Data-Forge and Data-Forge Notebook http://www.data-forge-js.com http://www.data-forge-notebook.com Web www.codecapers.com.au Open source https://github.com/ashleydavis https://github.com/data-forge https://github.com/data-forge-notebook Skills Quickly building MVPs for startups Understanding how to get the most out of technology for business Developing technical strategies Management and coaching of teams & projects Microservices, devops, mobile and fullstack software development
Updated on June 24, 2022Comments
-
romu almost 2 years
I would like to implement a general purpose runtime type conversion function that makes use .Net TypeConverters to do the conversion.
Does anyone know how to how to look up and invoke a TypeConverter for a particular type?
Consider this C# example:
// // Convert obj to the type specified by 'toType'. // object ConvertTo(object obj, Type toType) { if (TypeIsEqualOrDerivesFrom(obj.GetType(), toType)) <-- I know how to implement this. { // The type of obj is the same as the type specified by 'toType' or // the type of obj derives from the type specified by 'toType'. return obj; } if (TypeConverterExists(obj.GetType(), toType) <-- How do I implement this? { // There exists a type convertor that is capable of converting from // the type of obj to the type specified by 'toType'. return InvokeTypeConverter(obj, toType); <-- How do I implement this? } throw new TypeConversionFailedException(); }
-
Marc Gravell almost 15 yearsNote that TypeConverter implementations can be added at runtime (via TypeDescriptor) - and the standard framework will pick that up - but reflection (above) won't pick up such additions; System.ComponentModel is designed to be very flexible at runtime...
-
Steve Dignan almost 15 yearsAh, good one... that issue has come up for us (yet) -- this code has been around our app for a while; it's good to have a fresh set of eyes review it. Thanks!
-
Marc Gravell almost 15 yearsTo be honest, in most cases you wouldn't ever see the difference... it isn't that common that people start adding runtime converters/descriptors. But it is possible (I've got an example on stackoverflow somewhere...)
-
romu almost 15 yearsIt is interesting to me to see both methods as I intend to use both reflection and TypeConverters.
-
Patrik Svensson over 12 yearsI don't think Convert.ChangeType uses type converters.
-
Thomas S. Trias about 12 yearsAlso, look at Enum.ToObject if you need to converter an integral type to an actual enumerated type.
-
jp2code almost 6 years@Marc - is there a way to create a method to return the type that I give? Like
public T ChangeType<T>(Object item)
? Specifically, I need to create a test to see if two (2) Objects are equal, but first I need to establish if they are the same type of object.