Replace all occurrences with the properties of an object The basic idea is to replace all special expressions, e.g., [%InvoiceNo%], [%DueDate%], in a string with the properties of an object, Invoice invoice.

string str = "Your invoice [%InvoiceNo%] will be due on [%DueDate%]";
Invoice invoice = new Invoice { InvoiceNo = "123456", DueDate = DateTime.Parse("2011.12.29") };
string result = GetNewValue(str, invoice);
//The expected result is: Your invoice 123456 will be due on 11/29/2011


I think the simplest way to implement GetNewValue() could be

private string GetNewValue(string str, Invoice invoice)
{
    str = str.Replace("[%InvoiceNo%]", invoice.InvoiceNo);
    str = str.Replace("[%DueDate%]", invoice.DueDate.ToString());
    return str;
}


However, in my case, Invoice has a hundred properties and the target string only contains one or two properties. I rewrite GetNewValue() in the way I think it should work more efficiently. Here is my code

private string GetNewValue(string str, Invoice invoice)
{
    List&lt;string&gt; expressions = new List&lt;string&gt;();
    List&lt;string&gt; fields = new List&lt;string&gt;();

    var startIndices = str.IndicesOf("[%");
    var endIndices = str.IndicesOf("%]");
    int startLen = "[%".Length;
    int endLen = "%]".Length;

    for (int i = 0; i &lt; startIndices.Count; i++)
    {
        expressions.Add(str.Substring(startIndices[i], 
                                      endIndices[i] - startIndices[i] + endLen));
        fields.Add(str.Substring(startIndices[i] + startLen, 
                                 endIndices[i] - startIndices[i] - startLen));
    }

    for (int i = 0; i &lt; expressions.Count; i++)
        str = str.Replace(expressions[i], invoice.GetValueByName(fields[i]).ToString());

    return str;
}


StringExtender IndicesOf()

public static List&lt;int&gt; IndicesOf(this string target, string search)
{
    List&lt;int&gt; indices = new List&lt;int&gt;();
    int startIndex = 0;
    int index;

    while ((index = target.IndexOf(search, startIndex)) &gt; -1)
    {
        indices.Add(index);
        startIndex = index + 1;
    }

    return indices;
}


GetValueByName() using Reflection

public class Invoice
{
    // Properties
    ......

    public object GetValueByName(string name)
    {
        PropertyInfo myProperty = typeof(Invoice).GetProperty(name);
        return myProperty.GetValue(this, null);
    }
}


How can I improve this code? Fast, less memory usage, or one-liner
Don't tell me the first approach is better. Orz
Thanks :)
You can do it in one loop instead of getting all the indexes separately. Just off the top of my head:

        string str = "Your invoice [%InvoiceNo%] will be due on [%DueDate%]";

        int startIndex = 0;

        while ((startIndex = str.IndexOf("[%", startIndex)) &gt; -1)
        {
            int endIndex = str.IndexOf("%]", startIndex);
            string exp = str.Substring(startIndex, endIndex - startIndex + 2);
            string field = str.Substring(startIndex + 2, endIndex - startIndex - 2);
            str = str.Replace(exp, invoice.GetValueByName(field).ToString());
            startIndex = 0;
        }


Some points to note here:


I assume you are guaranteed to see the %] if you find the [%
I didn't test for edge cases like what if str = "[%invoice%]"


This is a neat solution but the more I think about your problem the more I wonder if you can engineer it so you pass what fields you want to your invoice object and it just returns you the correct string so you don't need to mess around with placeholders... food for thought :)