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
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...
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
> [...]
> 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
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...
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...
> 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
> 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
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