Formatted object properties with ToString() method

  • Thread starter Hans-Jürgen Philippi
  • Start date
H

Hans-Jürgen Philippi

Hi group,

let's say I have a 'Person' class with properties like 'FirstName',
'LastName', 'Birthday' and so on. Now I overload the 'Person' ToString()
method with an implementation ToString(string PlaceholderString) of the
following purpose:

When someone calls ToString("{LastName}, {FirstName}") on a given Person
instance, the expected result is e.g. "Doe, John" for this object, that is:
Any {property placeholder} is replaced by the actual instance value.
Furthermore, the ToString(string PlaceholderString) implementation is
intended to work with arbitrary properties on any class, without knowing the
members before.

I've achieved this with reflection: When ToString(string PlaceholderString)
is called, I loop over the type members to fetch the currently available
member/value pairs. In the same run, I do simple StringBuilder replacements
of requested {property placeholder} values within the user given
PlaceholderString and finally hand the replacement result out.

The whole thing works fine, I'm just asking myself: Is there a
better/faster/more efficient way to do this? Or did I reinvent the wheel and
there is an unknown .NET method with exactly the same function already?

Any hint is greatly appreciated.

Best regards,
Hans
 
I

Ignacio Machin ( .NET/ C# MVP )

The whole thing works fine,

have you tried how expensive this is in a loop? like when doing
databinding? Reflection in general is an expensive proposition that
should be used with care.
I'm just asking myself: Is there a
better/faster/more efficient way to do this?
not with those requirements,

Of course it should be trivial (only a few more keystrokes) to call
String.Format("{0}, {1}") , FirstName, LastName)
Or did I reinvent the wheel and
there is an unknown .NET method with exactly the same function already?

only the above mentioned String.Format and frankly I do not see the
need of another option

what is superior in your method than using String.Format?
 
I

Ignacio Machin ( .NET/ C# MVP )

what is superior in your method than using String.Format?

I'm going to answer that myself :)

The only advantage is that you can get that string from an external
source (like a DB or a config file)
 
M

Marc Gravell

Reflection in general is an expensive proposition that
should be used with care.

There are ways around this performance hit in the general case...

In this /specific/ case, I suspect the formatting etc will eat a
comparable amount of CPU, so I won't bother posting the details - but it
can be done ;-p More for things like bulk export/import...

Marc
 
H

Hans-Jürgen Philippi

You name it - this is exactly one of our use cases where we'd have external,
user created XML/HTML templates with content like "<div>Hello {Salutation}
{LastName}, ...</div>"!
I want to send them through the mentioned ToString() overload without caring
about the actual members of the target class.

Yes, I know that reflection is expensive. Therefore I wondered if there may
be an optimized way to get this kind of instance self-information for my
purpose.

Regards,
Hans


Newsbeitrag
 
M

Mihai N.

I'm going to answer that myself :)
The only advantage is that you can get that string from an external
source (like a DB or a config file)

Another one: localization.
When a translator gets "To {0} {1}" he has no clue what the heck this is all
about. "To {firstName} {lastName}" is self-explanatory.
 
G

Göran Andersson

Hans-Jürgen Philippi said:
Hi group,

let's say I have a 'Person' class with properties like 'FirstName',
'LastName', 'Birthday' and so on. Now I overload the 'Person' ToString()
method with an implementation ToString(string PlaceholderString) of the
following purpose:

When someone calls ToString("{LastName}, {FirstName}") on a given Person
instance, the expected result is e.g. "Doe, John" for this object, that is:
Any {property placeholder} is replaced by the actual instance value.
Furthermore, the ToString(string PlaceholderString) implementation is
intended to work with arbitrary properties on any class, without knowing the
members before.

I've achieved this with reflection: When ToString(string PlaceholderString)
is called, I loop over the type members to fetch the currently available
member/value pairs. In the same run, I do simple StringBuilder replacements
of requested {property placeholder} values within the user given
PlaceholderString and finally hand the replacement result out.

The whole thing works fine, I'm just asking myself: Is there a
better/faster/more efficient way to do this? Or did I reinvent the wheel and
there is an unknown .NET method with exactly the same function already?

Any hint is greatly appreciated.

Best regards,
Hans

How about this:

string[] props = new string[] { "FirstName", "LastName", "Birthday" };
string format = Regex.Replace(PlaceHolderString, @"\{(\w+)\}",
delegate(Match m) { for (int i = 0; i < props.Length; i++) if
(m.Groups[1].Value == props) return "{" + i.ToString() + "}"; return
m.Value; });
return string.Format(format, FirstName, LastName, Birthday);

Just add the names of the properties in the array and in the Format call.
 
H

Hans-Jürgen Philippi

Hi Göran,

the way you use a regular expression to derive a format string is nice. But
doing it like this, you need to know the class properties at design time and
have to maintain a lookup array as well as a custom fitting String.Format()
method by hand - where I wanted an approach to have ToString(string
PlaceholderString) generally working even in derived classes with completely
new, unforeseen members!
Maybe I mix my implementation with your code to create the props and
String.Format() args arrays dynamically via reflection and benefit from the
cool Regex appeal. ;-)

Well, it appears like reflection is the tradeoff for the flexibility I need
and there will hardly be a much more efficient (=faster, reliable, easy on
resources *and* easy to maintain) way to do this.

Thanks for your input,
Hans
 
M

Marc Gravell

and there will hardly be a much more efficient (=faster, reliable, easy on
resources *and* easy to maintain) way to do this.

Efficiency is tricky to define ;-p

For example, HyperDescriptor is significantly quicker at execution
(especially if you re-use the PropertyDescriptorCollection), but has
to generate a dynamic assembly on the fly, so bigger footprint (not by
much). Identical from a maintenance perspective.

http://www.codeproject.com/KB/cs/HyperPropertyDescriptor.aspx
[this is what I hinted at previously, but didn't post...]

Marc
 
H

Hans-Jürgen Philippi

Hi Marc,
Efficiency is tricky to define ;-p

Yep, definitely true. :)

For example, HyperDescriptor is significantly quicker at execution
(especially if you re-use the PropertyDescriptorCollection), but has
to generate a dynamic assembly on the fly, so bigger footprint (not by
much). Identical from a maintenance perspective.

http://www.codeproject.com/KB/cs/HyperPropertyDescriptor.aspx
[this is what I hinted at previously, but didn't post...]

Thanks for pointing me to this, I didn't know it before and it looks pretty
interesting. Don't be too modest, doing good things and not speaking about
it! ;-)


Greetings,
Hans
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top