[.net] Converting strings to arbitrary types?

Started by
8 comments, last by dalep 18 years, 2 months ago
Is there any way to programatically convert a string of data into an arbitrary type in .net? For example; I have a type that has an unspecified set of fields, which my system doesn't know about at design-time, seeing as how I'm dynamically creating types at run-time. Now I want to be able to deserialize string data into any dynamically created object (I've already looked at SOAPFormatter, but it will not work with what I'm doing; SOAP uses very strong naming of assemblies, my system does not use strong naming of assemblies at all, plus I need the ability to stream portions of data into a pre-existing object, and possibly transfer data between different types), but I've run into a problem. When I get a list of all the fields in a datatype, and I have the string data that I want to store into those fields, I don't see any easy way to convert that string into that type. I can use the Convert class, but that requires me to create a switch statement for each basic type, and doesn't allow me to expand my classes using non-basic datatypes. Basically, what I'm wondering is, why isn't there any .FromString() function, or conversion operator like in C++? And if there is, why can't I seem to find it? FieldInfo.SetValue() won't work for my purposes, by the way, since it cannot implicitly convert strings to numeric data types
This is my signature. There are many like it, but this one is mine. My signature is my best friend. It is my life. I must master it as I must master my life. My signature, without me, is useless. Without my signature, I am useless.
Advertisement
I'm not sure if this might help you, but have you looked into reflection? With Reflection you CAN convert things into their type based upon strings.

Note: I never used Reflection myself, but I've seen it can be used to convert strings to enums, so it's bound to work for dynamic created classes.

Toolmaker

Have you taken a look at ComponentModel.TypeConverter? It is what the framework uses to drive the PropertyGrid control. A bit clunky for my tastes. Anyway I think it supports most of the primitive types and can convert them to and from strings. Other types you will probably have to deal with yourself -- or try to extend TypeConverter(use a custom type converter? -- whatever it is they want you do. I recall it being somewhat of a nightmare.)

If you want to use reflection you can cover the primitives by looking for a Parse or TryParse method via reflection (Why did they choose not to make an interface IParsable or somehting, I do not know) anyway, they all have these methods and the signatures are the same so you can use invoke on the MethodInfo or if you are concerned with speed do some Emitting (probably way beyond what you need).

see:
ComponentModel.TypeConverter
Type.GetMethod
MethodInfo.Invoke

One more thing: Some of the XML stuff seems to be able to do this -- for example XPathNavigator has a ValueAs method that does type conversion of course you may have already looked over the XML stuff if you were playing SOAP.


Hope this helps.
I've done this with a class that surrounds a static Dictionary<type,delegate>, which automatically adds type.Parse for the primitives. Quite effective.
Quote:Original post by Telastyn
I've done this with a class that surrounds a static Dictionary<type,delegate>, which automatically adds type.Parse for the primitives. Quite effective.


Dynamic, easy to extend with custom parsing delegates should be reasonably fast. Very smart. How do you make your delegates? new Delegaete(type,methodName) or some other way? Do you invoke with DynamicInvoke or can you cast the delegates to an object Foo(string) form? Just interested. I have been playing with DynamicMethod and some other Emit stuff myself in a similar context. Trying avoid the heavy costs of reflection and still get some serious felxability.
Let's see...

Simply object delegate(string). Requires the programmer to cast to, anon-delegate or otherwise specify that delegate type when adding to the class.

The main use for this class is in a quake-style console parser. The returned object is often stuffed into an object[] and passed to DynamicInvoke.

This was actually some of my first C# code, as I've a similar C++ serialization registry. It though uses template instantiation with static functors.
You could try out XML Serialization as XML can be interpretted as a plain string. Although it's quite tricky to get into, it's a really handy tool. The only thing I don't like about it is that if something is not exactly right with the Schema, then it doesn't work. Here are some articles.
Rob Loach [Website] [Projects] [Contact]
C# has conversion operators (don't know about other .NET languages), but generating a static Parse() method for your dynamic types would be better. You can then use reflection to find the Parse() method for the type your trying to create (the reason for calling it Parse() is this will also work with the built-in types like System.Int32) and call it to create the instance. Something like this:

public static object FromString(Type type, string value){    // Find the Parse method    MethodInfo parser = type.GetField(type, BindingFlags.Static);    if(parser==null) throw new InvalidOperationException("No static Parse() method");    // Create the instance    return parser.Invoke(null, new object[] { value });}


Your generated Parse() methods would parse the string and possibly call FromString as needed for creating instances for its fields.


EDIT: Hmmm, seems like I've just repeated part of what turnpast said [smile]
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V
I've had fun with implicit type casts from strings before. I wrote a point class one time that had an implicit cast that would parse strings in the format "(x,y)".

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

turnpast is right - the proper way to do this is to write a TypeConverter and attach it to your class with the TypeConverter attribute. Then you can use Convert.ToXXX on your class just like you do on anything else.

This topic is closed to new replies.

Advertisement