|
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.
Irish guy living in Seattle who is passionate about technology, running, trail running. Software Engineer @Microsoft by day (and night too
)
He is an ex Codeproject Editor... time restrictions are still a problem.