Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ToString and FromString

15 views
Skip to first unread message

shapper

unread,
May 12, 2009, 4:23:24 PM5/12/09
to
Hello,

I created a TypeConverter to convert a List<Tag> to a from String.

For example, List<Tag> to String all I need to do is:

String tags = MyListTags.ToString();

But how to make the inverse conversion? From String to List<Tag>?
I would need something like FromString ...

I am just not sure how to apply my converter in this case.

This is my Type Converter code:

public class TagsConverter : TypeConverter {

// CanConvertFrom
public override Boolean CanConvertFrom(ITypeDescriptorContext
context, Type sourceType) {
return sourceType == typeof(IList<Tag>) ? true :
base.CanConvertFrom(context, sourceType);
} // CanConvertFrom

// CanConvertTo
public override Boolean CanConvertTo(ITypeDescriptorContext
context, Type destinationType) {
return destinationType == typeof(String) ? true :
base.CanConvertTo(context, destinationType);
} // CanConvertTo

// ConvertFrom
public override Object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, Object value) {
if (value is String) {
String tags = (String)value;
return tags.Split(new char[] { ',' },
StringSplitOptions.RemoveEmptyEntries).Select(t => new Tag() { Name =
t.Trim() }).ToList();
}
return base.ConvertFrom(context, culture, value);
}

// ConvertTo
public override Object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, Object value, Type destinationType) {
if (value is List<Tag>) {
List<Tag> tags = (List<Tag>)value;
return String.Join(", ", tags.Select(t => t.Name).ToArray());
}
return base.ConvertTo(context, culture, value, destinationType);
} // ConvertTo

} // TagsConverter

And I am registering it as follows:
TypeDescriptor.AddAttributes(typeof(List<Tag>), new
TypeConverterAttribute(typeof(TagsConverter)));

Thanks,
Miguel

Stanimir Stoyanov (C# MVP)

unread,
May 12, 2009, 7:33:37 PM5/12/09
to
Hello Miguel,

If you are compiling against C# 3.5 or later, it is easy to write an
extension method called FromString accessible from all List<Tag> instances,
populating the given instance.

internal static class Extensions
{
internal static void FromString(this List<Tag> list, string
tags)
{
List<Tag> newTags = (List<Tag>)new
TagsConverter().ConvertFromString(tags);

list.AddRange(newTags);
}
}

The above will make it possible to use the following syntax:

List<Tag> tags = new List<Tags>();

tags.FromString("tag, another, test"); // Note that FromString does
not return anything, but populates the list.

You might consider clearing the existing list in the FromString method body
or avoid adding duplicates.

For every other .NET versions you can create a helper class with a static
method similar to the extension one.

HTH,
--
Stanimir Stoyanov
Microsoft MVP -- Visual C#
http://stoyanoff.info

"shapper" <mdm...@gmail.com> wrote in message
news:458dbba2-d2eb-4ec5...@s16g2000vbp.googlegroups.com...

shapper

unread,
May 12, 2009, 7:47:31 PM5/12/09
to
On May 13, 12:33 am, "Stanimir Stoyanov \(C# MVP\)"

<stoya...@REMOVETHIS.live.com> wrote:
> Hello Miguel,
>
> If you are compiling against C# 3.5 or later, it is easy to write an
> extension method called FromString accessible from all List<Tag> instances,
> populating the given instance.
>
>         internal static class Extensions
>         {
>             internal static void FromString(this List<Tag> list, string
> tags)
>             {
>                 List<Tag> newTags = (List<Tag>)new
> TagsConverter().ConvertFromString(tags);
>
>                 list.AddRange(newTags);
>             }
>         }
>
> The above will make it possible to use the following syntax:
>
>         List<Tag> tags = new List<Tags>();
>
>         tags.FromString("tag, another, test"); // Note that FromString does
> not return anything, but populates the list.
>
> You might consider clearing the existing list in the FromString method body
> or avoid adding duplicates.
>
> For every other .NET versions you can create a helper class with a static
> method similar to the extension one.
>
> HTH,
> --
> Stanimir Stoyanov
> Microsoft MVP -- Visual C#http://stoyanoff.info
>
> "shapper" <mdmo...@gmail.com> wrote in message

Thank You Stanimir,

I am using NET 3.5 and I was looking exactly for an extension but I
was not being able to create it.
I was trying to create a generic extension List<T> to convert any list
to a String.
This way any list I have and that I apply ToString I would fire the
correspondent convert since there is not ToString in List.

Is this possible?

Thanks,
Miguel

Peter Duniho

unread,
May 12, 2009, 7:56:26 PM5/12/09
to
On Tue, 12 May 2009 16:33:37 -0700, Stanimir Stoyanov (C# MVP)
<stoy...@removethis.live.com> wrote:

> [...]


> tags.FromString("tag, another, test"); // Note that FromString
> does not return anything, but populates the list.

IMHO, the fact that the method doesn't return something is a very good
reason to not call it "FromString()". For the method you posted, I would
name it "AddFromString()", since that's what it does. If you clear the
List<T> first, maybe "CopyFromString()" would be better.

The name "FromString()" strongly implies that the method will return a new
List<T> instance.

Pete

Stanimir Stoyanov (C# MVP)

unread,
May 12, 2009, 8:02:27 PM5/12/09
to
> I was trying to create a generic extension List<T> to convert any list
> to a String.
> This way any list I have and that I apply ToString I would fire the
> correspondent convert since there is not ToString in List.
>
> Is this possible?

If I understand correctly, you want to write a ToString() extension method
as with FromString(string). In this case, you have to use another name (e.g.
ToTagString()) *or* method signature because the List<Tag> class already has
a parameterless ToString() method inherited from System.Object.

It would still use TagsConverter to perform the conversion but this will
this help you writer cleaner code, avoiding redundancies.

--
Stanimir Stoyanov


Microsoft MVP -- Visual C#
http://stoyanoff.info

"shapper" <mdm...@gmail.com> wrote in message

news:810ffd69-7563-4f1c...@r3g2000vbp.googlegroups.com...

Stanimir Stoyanov (C# MVP)

unread,
May 12, 2009, 8:05:34 PM5/12/09
to
Thanks, Pete, this is a valid point.

At first I was contemplating suggesting a string extension method, for which
FromString() would be a suitable name. However, I eventually decided that
extending the string class solely for use with List<Tag> would be a bad
design.

--
Stanimir Stoyanov
Microsoft MVP -- Visual C#
http://stoyanoff.info

"Peter Duniho" <NpOeS...@nnowslpianmk.com> wrote in message
news:op.utucs...@macbook-pro.local...

Peter Duniho

unread,
May 12, 2009, 8:19:39 PM5/12/09
to
On Tue, 12 May 2009 13:23:24 -0700, shapper <mdm...@gmail.com> wrote:

> Hello,
>
> I created a TypeConverter to convert a List<Tag> to a from String.
>
> For example, List<Tag> to String all I need to do is:
>
> String tags = MyListTags.ToString();

Are you sure that works as you expect it to? MSDN suggests that you ought
to be using the TypeDescriptor class to retrieve the appropriate
TypeConverter instance, and calling its methods directly.

> But how to make the inverse conversion? From String to List<Tag>?
> I would need something like FromString ...
>
> I am just not sure how to apply my converter in this case.

I'm not all that familiar with TypeConverter. However, looking at your
code it _seems_ to me that you've reversed the sense of the
CanConvertFrom() and CanConvertTo() methods. At the very least,
CanConvertFrom() should return "true" if the input is also an
appropriately-formed string, as well as if it's an IList<Tag>.

You should post a concise-but-complete code sample that reliably
demonsrates the problem, if the above doesn't seem to be applicable
information.

I will also point out that you are treading in dangerous territory, trying
to map a List<T> to and from a comma-separated string. There's nothing in
your code that deals with commas in the Tag itself. One hopes that you
know for sure that the Name property for a Tag instance will never ever
have a comma in it, but if that's the assumption you're making, you need
to throw an exception if you wind up ever trying to convert a list of Tags
where one does have a comma.

Also, the string you generate uses ", " as the delimiter between tags, but
the delimeter used for splitting the string back into Tag instances uses
just ",". Again, your code is assuming that a Tag will never have a
leading or trailing space in the Name property, because instead of
correctly using the same delimiter in both places, you simply call Trim()
on the split string.

Finally, you are using the "RemoveEmptyEntries" option for Split, which
again can cause problems if you wind up with a Tag that has an empty
string as the Name property.

For all of these assumptions, you really should make the code in
ConvertTo() check those assumptions and throw an exception if they wind up
invalidated by the input data. Because otherwise, you run the risk of
having subtle, hard-to-track-down bugs if and wind the input data winds up
invalid.

Pete

Peter Duniho

unread,
May 12, 2009, 8:28:54 PM5/12/09
to
On Tue, 12 May 2009 16:47:31 -0700, shapper <mdm...@gmail.com> wrote:

> I am using NET 3.5 and I was looking exactly for an extension but I
> was not being able to create it.
> I was trying to create a generic extension List<T> to convert any list
> to a String.
> This way any list I have and that I apply ToString I would fire the
> correspondent convert since there is not ToString in List.
>
> Is this possible?

You should be careful with the word "extension". If you want an actual
extension method, you should write "extension method" for clarity. If you
don't want an extension method, you should avoid the word "extension" at
all, at least without further clarification.

Assuming we're still working with the TypeConverter example, I will point
out that the problems I mentioned with respect to converting a List<Tag>
instance because even more critical with a general-purpose conversion. In
your List<Tag> converter, you are able to select the property of the class
you want, and presumably you have some guarantees about how it's formatted.

But for List<T> in general, there is no guarantee that you can even have a
one-to-one mapping between a string and a T element of the list, never
mind that the string version of a T element will fit the assumptions that
your conversion code makes.

I would say the most significant barrier you'll run into is the general
lack of a "from string" conversion for most types. But all the other
issues are ones you'll have to consider as well.

Pete

Cor Ligthert[MVP]

unread,
May 13, 2009, 1:36:50 AM5/13/09
to
Miquel,

Be aware that ToString() is not direct a type converter, it is a property
which returns the name of the Type as it is not overridden. With all value
types it is overridden to return the value as a string, but it can be
overridden in any other way.

Cor

0 new messages