Ricky Wang

With C#, is it possible to implement a generic type conversion function that contains two parameters, one is the value (object type) to be converted and the other is target type's identifier (a string) that the value is to be converted to.

For example, the function signature looks like

public static object GenericConverter(object value, string targetTypeName) {

// implemation

}

and we may make use of it as: int a = GenericConverter("1", "System.Int32"); or

bool b = GenericConverter("false", "System.Boolean");

Any suggestion is welcome.

Ricky.




Re: Visual C# Language A generic type conversion problem

marco.ragogna

Code Snippet

public static object GenericConverter(object value, string targetTypeName) {

object result = null;

Type type = Type.GetType(targetTypeName);

if (type != null)

{

result = Convert.ChangeType(result, type);

}

return result;

}

This could be solution but pay attention to the fact the the method ChangeType accepts only objects that implement the interface IConvertible. In addition to that the GetType method can resolve only basic types or types loaded in the currenct executing assembly.

I am not sure but I have the feeling that this is not useful for you. Can you explain us more in detail for what are you planning to use this GenericConverter

You can also look to the class System.ComponentModel.TypeConverter..





Re: Visual C# Language A generic type conversion problem

Peter Ritchie

If I may ask, why do you want to do it this way Using a string for the type will require that you use Reflection, which will be really slow.

You could use an explict conversion:

Code Snippet
class SomeType
{
public static explicit operator SomeType (int i)
{
// code to convert from int to SomeType
}
}

Or, you could use the TypeConverterAttribute and the TypeConverter class to create a custom converter (See also Generialized Type conversion):

Code Snippet
namespace Application1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
MyType myType = new MyType(666);
int value = (int)TypeDescriptor.GetConverter(myType.GetType()).ConvertTo(myType, typeof(int));
Console.WriteLine(value); // outputs 666
value = 42;
myType = TypeDescriptor.GetConverter(myType.GetType()).ConvertFrom(value) as MyType;
Console.WriteLine(myType.Value); // outputs 42
}
[TypeConverter(typeof(MyTypeConverter))]
public class MyType
{
int value;
public MyType(int value)
{
this.value = value;
}
public int Value { get { return value; } set { this.value = value; } }
}
public class MyTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(int) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(int) || base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is int)
{
return new MyType((int)value);
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
MyType myType = value as MyType;
if (destinationType == typeof(int) && myType != null)
{
return myType.Value;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}






Re: Visual C# Language A generic type conversion problem

Kea

You could use an early-bound approach:

Code Snippet

public static U Convert<T, U>(T source)

{

// The cast cannot be known to be possible.

// You can use

// if (source is U)

// or

// U u = source as U;

// if (u != null)...

// But how do you want to notify the caller

try { return (U)source; }

catch (InvalidCastException) { throw; }

}






Re: Visual C# Language A generic type conversion problem

George Olson

Great idea, but I could not get it to compile. Here is another version that converts instead of casts.

Code Snippet

public class GenericConverter<Tin, Tout>

{

public static Tout ConvertFromGeneric(Tin tin)

{

return (Tout)Convert.ChangeType(tin, typeof(Tout));

}

}

Use it like

Code Snippet

Console.WriteLine(GenericConverter<int, string>.ConvertFromGeneric(4));





Re: Visual C# Language A generic type conversion problem

Kea

You should never use generics like that. Static methods should always use their own type parameters. The following works, though:

Code Snippet

public class Conversion
{
public static TOut Convert<TIn, TOut>(TIn source)
where TIn : class
where TOut : class
{
return source as TOut;
}

public static void TestGConv()
{
object o = Convert<string, object>("Hello");

if (o != null && o.ToString() == "Hello")
System.Diagnostics.Debug.WriteLine("Generic class cast works.");
else
System.Diagnostics.Debug.WriteLine("Generic class cast doesn't work.");
}
}


It just has to be of a class type, because only casts between classes make sense, otherwise conversion must be used.
But there doesn't exist any use of this code at all. You can get away with writing the code directly, so it's just a difficult way to do it. However it demonstrates the power of CLR generics.




Re: Visual C# Language A generic type conversion problem

Ricky Wang

My original intent is to set a object's (says obj) properties from a .xml file that may contain the following structures:

<b>

<c value="5" typeStr="System.int32" />

</b>

where "b" is of a member of obj and b in turn has a property "c" that is of the int32, which is going to be set to 5.

In desgin time, it is very simple to write as obj.b.c = 5;

However, with properties' values as string stored in xml attributes, I must strive to convert (generate) the them to the right type designated by type attribute.

And let me apologize for my incorrect description of my original problem. My problem should be: if we can write a generic convert function to convert a string value to the designated type (or class). Because there is no such method - Convert.ToColor("Red");

and even if we parse the typeStr, we still need to to write a bunch of if... else if... to convert the string value to the right type like:

Code Snippet

public object Converter(string value, string typeStr) {

if (typeStr == "System.Double") {

return Convert.ToDouble(value);

}

else if (typeStr == "System.int32") {

return Convert.ToInt32(value);

}

}

Thanks a lot for every one's valued suggestion.

Ricky.






Re: Visual C# Language A generic type conversion problem

James Curran

Have you looked into the XmlSerializer class It seems you are going through a lot of work to duplicate something that is already written.






Re: Visual C# Language A generic type conversion problem

George Olson

Kea, can you please help My original though was to overload the method for a delegate. Between the two which should be used, or is there a better way to do it

Code Snippet

static void Main(string[] args)

{

Console.WriteLine(GenericConverter2.ConvertFromGeneric<int, string>(4, delegate(int i)

{

return i.ToString();

}));

Console.ReadLine();

}

public class GenericConverter<Tin, Tout>

{

public delegate Tout Transform(Tin tin);

public Tout ConvertFromGeneric(Tin tin)

{

return (Tout)Convert.ChangeType(tin, typeof(Tout));

}

public Tout ConvertFromGeneric(Tin tin, Transform transform)

{

return (Tout)transform(tin);

}

}

public class GenericConverter2

{

public delegate Tout Transform<Tin, Tout>(Tin tin);

public static Tout ConvertFromGeneric<Tin, Tout>(Tin tin)

{

return (Tout)Convert.ChangeType(tin, typeof(Tout));

}

public static Tout ConvertFromGeneric<Tin, Tout>(Tin tin, Transform<Tin,Tout> transform)

{

return (Tout)transform(tin);

}

}





Re: Visual C# Language A generic type conversion problem

Kea

George, no, this is getting off-topic so I don't feel I should pursue it.

As for the original question, I think XmlSerializer would be the best approach. However I understand there may be a problem if the input must be in a format incompatible with XmlSerializer. I also think he is not talking about generics as in type parameterization, but for generic usage. I think this is a simple straight forward way to do it, assuming you only use primitive value types:

Code Snippet
public static object ConvertValueType(string value, string targetTypeName)
{
try
{
switch (targetTypeName)
{
case "System.Boolean":
return bool.Parse(value);
case "System.Byte":
return byte.Parse(value);
case "System.Int16":
return short.Parse(value);
case "System.Int32":
return int.Parse(value);
case "System.Int64":
return long.Parse(value);
case "System.SByte":
return sbyte.Parse(value);
case "System.UInt16":
return ushort.Parse(value);
case "System.UInt32":
return uint.Parse(value);
case "System.UInt64":
return ulong.Parse(value);
case "System.Single":
return float.Parse(value);
case "System.Double":
return double.Parse(value);
case "System.String":
return string.Parse(value);
case default:
return null;
}
}
catch { return null; }
}



The result should be automatically boxed, and you can use FieldInfo.SetValue() after having acquired one. You get null if the value couldn't be converted (parsed or wasn't hard-coded).




Re: Visual C# Language A generic type conversion problem

Kea

There's a syntax error: the line 'case default:' should be just 'default:', but the post edit didn't work (and hasn't worked for many months). I also forgot to put in 'break;' before every next switch, which is required in C#. I couldn't remove the string.Parse() part either, in that case it could just return the same object since the string value is the parsed string itself.




Re: Visual C# Language A generic type conversion problem

Vivek Ragunathan

Hi

Correct me if i am wrong - You have to read data from xml and you need classes that help you in reading and writing data and be type aware.

If that is the case, generate a xsd for your xml.

And use the xsd compiler [in the prebuild step] to compile the xsd to generate a design time C# class.

now you can use the C# class to acess the values and they are type aware.

Hope that helps.

Regards





Re: Visual C# Language A generic type conversion problem

George Olson

Ricky,

Has anyone's post been helpful so far Either way can you let us know on your progress





Re: Visual C# Language A generic type conversion problem

Ricky Wang

George Olson wrote:

Ricky,

Has anyone's post been helpful so far Either way can you let us know on your progress

At the moment, the approach most closest to mine is of Kea's reply where the "switch...case" is used to check the type identifier (a string) and convert the source value (string type) to the value with designation type. In addition, one more case condition can be appended:

Code Snippet

case "System.Drawing.Color":
return TypeDescriptor.GetConverter(typeof(Color)).ConvertFromString(value); // value may be "Red", "Blue", etc

But I have not studied the XMLSerializer to see if it is feasible for me. The object to be set is an web server control and is dragged into Page in design time. During Page_Load(), I manage to set its properties according to the Xml.

Thanks again for your enthusiastic replies.

Cheers,

Ricky.






Re: Visual C# Language A generic type conversion problem

Ricky Wang

Hi kea,

You are right. I am seeking a tactics for designing a generic-purpose type converter.

Ricky.