Click here to Skip to main content
15,886,030 members
Articles / Programming Languages / C#

Regular Expression Library Builder

Rate me:
Please Sign up or sign in to vote.
4.63/5 (24 votes)
14 Jun 2005CPOL7 min read 142.5K   3.5K   92  
A tool to quickly allow the creation and modification of .NET Regular Expression Libraries
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Formatters.Binary;

using Dela.RegexLibraryBuilder.Collections;

namespace Dela.RegexLibraryBuilder
{
	/// <summary>
	/// Summary description for RegexLibraryBuilder.
	/// </summary>
	public sealed class RegexLibraryBuilder
	{
      #region Nested Classes

      private class RegexLibraryLoader : System.MarshalByRefObject
      {
         #region Fields

         private RegexCompilationInfoCollection _regexs;
         private AssemblyName _assemblyName;

         #endregion

         #region Properties

         public RegexCompilationInfoCollection Regexs
         {
            get
            {
               return _regexs;
            }
         }

         public AssemblyName AssemblyName
         {
            get
            {
               return _assemblyName;
            }
         }


         #endregion

         #region Constructors

         public RegexLibraryLoader()
         {
         }

         #endregion

         #region Public Methods

         public void LoadRegexLibrary(string assemblyLocation)
         {
            // Load the assembly
            Assembly regexLibrary = Assembly.LoadFrom(assemblyLocation);

            //Extract the relevant details from the assembly
            _regexs = ExtractRegexs(regexLibrary);
            _assemblyName = ExtractAssemblyDetails(regexLibrary);
         }

         #endregion

         #region Private Methods

         private RegexCompilationInfoCollection ExtractRegexs(Assembly regexLibrary)
         {
            RegexCompilationInfoCollection regexs = null;

            // Loop through all the types in the assembly
            foreach(Type type in regexLibrary.GetTypes())
            {
               // Only interested in types with a base type of System.Text.RegularExpressions.Regex
               if(type.BaseType == typeof(System.Text.RegularExpressions.Regex))
               {
                  // If this is the first valid type found, create the collection to store it.
                  if(regexs == null)
                  {
                     regexs = new RegexCompilationInfoCollection();
                  }

                  // Create an instance of the type and extract the necessary details from it.
                  Regex regex = regexLibrary.CreateInstance(type.FullName) as Regex;
                  string pattern = type.GetField("pattern", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(regex).ToString();
                  object options = type.GetField("roptions", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(regex);

                  // Create a new RegexCompilationInfo object from the extracted details and add to the collection
                  if(options != null && options is RegexOptions && pattern != null)
                  {
                     regexs.Add(new RegexCompilationInfo(pattern, (RegexOptions)options, type.Name, type.Namespace, type.IsPublic));
                  }
               }
            }

            return regexs;
         }

         private AssemblyName ExtractAssemblyDetails(Assembly regexLibrary)
         {
            return regexLibrary.GetName();
         }

         #endregion
      }

      #endregion

      #region Fields

      private string _assemblyLocation;
      private RegexCompilationInfoCollection _regexs;
      private AssemblyName _assemblyName;

      public delegate void LibraryLoadedDelegate(RegexCompilationInfoCollection regexs, AssemblyName assemblyName);

      #endregion

      #region Properties

      public RegexCompilationInfoCollection Regexs
      {
         get
         {
            return _regexs;
         }
         set
         {
            if(Regexs == null || Regexs.Count == 0)
            {
               throw new ArgumentException("RegexCompilationInfoCollection cannot be null or empty!");
            }

            _regexs = value;
         }
      }

      public AssemblyName AssemblyName
      {
         get
         {
            if(_assemblyName == null)
            {
               _assemblyName = new AssemblyName();
            }
            return _assemblyName;
         }

         set
         {
            if(value == null)
            {
               throw new ArgumentException("AssemblyName cannot be null!");
            }

            _assemblyName = value;
         }
      }


      #endregion

      #region Events

      public event LibraryLoadedDelegate LibraryLoaded;

      #endregion

      #region Constructors

      public RegexLibraryBuilder()
      {
         _regexs = new RegexCompilationInfoCollection();
      }
		
      #endregion

      #region Public Methods

      public void LoadRegexLibrary(string assemblyLocation)
      {
         if(assemblyLocation == null)
         {
            throw new ArgumentException("Argument cannot be null", "assemblyLocation");
         }

         if(assemblyLocation.IndexOfAny(Path.InvalidPathChars) > -1)
         {
            throw new ArgumentException("Assembly location contains invalid path characters", "assemblyLocation");
         }

         _assemblyLocation = assemblyLocation;
         LoadRegexLibrary();

         // Fire LibraryLoaded event
         if(LibraryLoaded != null)
         {
            LibraryLoaded(_regexs, _assemblyName);
         }
      }

      public void SaveRegexLibrary(RegexCompilationInfoCollection regexs)
      {
         this.Regexs = regexs;
         SaveRegexLibrary();
      }

      public void SaveRegexLibrary(AssemblyName assemblyName)
      {
         this.AssemblyName = assemblyName;
         SaveRegexLibrary();
      }

      public void SaveRegexLibrary(RegexCompilationInfoCollection regexs, AssemblyName assemblyName)
      {
         this.AssemblyName = assemblyName;
         this.Regexs = regexs;
         SaveRegexLibrary();
      }


      public void SaveRegexLibrary()
      {
         if(_assemblyName == null)
         {
            throw new InvalidOperationException("Cannot create regex library if AssemblyName is null!");
         }

         // Compile everything to an assembly!
         Regex.CompileToAssembly(_regexs.ToArray(), _assemblyName);
      }

      #endregion

      #region Internal Methods

      private void LoadRegexLibrary()
      {
         if(File.Exists(_assemblyLocation) == false)
         {
            throw new InvalidOperationException("Cannot load '" + _assemblyLocation + "' as it does not exist!");
         }

         // Create a temporary application domain to load the regex assembly into
         AppDomain tempDomain = AppDomain.CreateDomain("TempDomain");

         // Create an instance of the nested RegexLibraryLoader class in the new domain.
         RegexLibraryLoader libraryLoader = tempDomain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, typeof(RegexLibraryLoader).FullName) as RegexLibraryLoader;

         libraryLoader.LoadRegexLibrary(_assemblyLocation);
         _regexs = libraryLoader.Regexs;
         _assemblyName = libraryLoader.AssemblyName;

         // Unload the temporary domain which unloads the regex library dll
         AppDomain.Unload(tempDomain);
      }

      #endregion
   }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Irish guy living in Seattle who is passionate about technology, running, trail running. Software Engineer @Microsoft by day (and night too Smile | :) )

He is an ex Codeproject Editor... time restrictions are still a problem.

Comments and Discussions