Usually I find it hard to make time to post anything about what I do on a regular basis. So out of many things going on, I figured I would post about a simple change or addition I made to some helper class methods I use pretty regularly in both asp.net and sharepoint programming. The biggest part of which is using the Type.InvokeMember() method of the .NET System namespace to make one method a little more generic.

My original need was to parse sharepoint rich text content fields for html image tags and remap the url to an asp.net image handler. At some point I’ll have to detail the whole image handler concept that I am talking about. For a simpler example, my most recent need was just to parse for any html anchor tags and make sure that a target=”_blank” attribute existed.  

This simple version is broken up into two methods. The first is just looking for the specific tag throughout the rich text. I found myself asking if there was a way to use the first method with any similar operation. Before realizing I could use InvokeMethod, I figured maybe a switch statement might work. If I took that route it meant adding case statements every time there was a new method for dealing with a certain tag or operation on a tag–kinda a pain. 


using System;
using System.Collections.Generic;
using System.Text;

public class Helpers
    {
        /// <summary>
        /// Use this method to do work on all specific tag instances in a string
        /// An example would be that you want to check that a target attribute exists in all anchor tags in the supplied string.
        /// DataStr would be the original string, tag would be "a" (it is case insensitive), and method would be ensureAtagBlankTarget.
        /// Notice ensureAtagBlankTarget is pretty specific and must be a method already in the Helpers class.
        /// </summary>
        /// <param name="DataStr">The original string</param>
        /// <param name="tag">The tag you want to work on</param>
        /// <param name="methodToRunOnTag">A method in the Helpers class that you want to operate on each instance of the tag searched for.</param>
        /// <returns></returns>
public static string stringTagIterator(string DataStr, string tag, string methodToRunOnTag)
        {
            if (DataStr.Length > 0)
            {
                StringBuilder newstr = new StringBuilder();
                int curPos = 0;
                int Loops = 0;
                do
                {
                    Loops++;
                    int tagLoc = DataStr.IndexOf("", tagLoc);
                    string tagstr = DataStr.Substring(tagLoc, (tagEndLoc + 1) - tagLoc);
                    newstr.Append(DataStr.Substring(curPos, tagLoc - curPos));
                    Type curclass = typeof(Helpers); //Helpers is the class this method is in
                    String tempstr = (String)curclass.InvokeMember(methodToRunOnTag, System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, null, new Object[] { tagstr });
                    newstr.Append(tempstr);
                    curPos = tagEndLoc + 1;

                } while (Loops < 10000); //just a way to keep this loop from getting too carried away
                newstr.Append(DataStr.Substring(curPos));
                return newstr.ToString();
            }
            else
            {
                return "";
            }
        }
        public static string ensureAtagBlankTarget(string dataStr)
        {
            dataStr = dataStr.Replace("<A ","<a ");
            if (dataStr.IndexOf("target=\"_blank\"", StringComparison.InvariantCultureIgnoreCase).Equals(-1))
                dataStr = dataStr.Replace("<a ", "<a target=\"_blank\" ");
            return dataStr;
        }
}

The second method does the specific work on the tag data and then passes it back. The whole point of this though is that stringTagIterator can be called with a specific tag in mind and the name of a method that you would like to have operate on the tag found.

Advertisement