C# - Usando Expressões Regulares compiladas


 Neste artigo vou mostrar como podemos minimizar o impacto no desempenho de uma aplicação que surge quando precisamos usar expressões regulares com frequência.

Por padrão, quando você cria um objeto Regex, o padrão da expressão regular especificado no construtor é compilado para uma forma intermediária (não MSIL). Então, cada vez que você usar o objeto Regex, o runtime interpreta a forma intermediária do padrão e aplica-o para a seqüência alvo.

Com expressões regulares complexas que são usados ​​com freqüência, esse processo de interpretação repetido pode ter um efeito negativo sobre o desempenho do seu aplicativo.

Ao especificar a opção RegexOptions.Compiled, quando você cria um objeto Regex, você força o runtime .NET a compilar a expressão regular para a MSIL em vez de usar forma intermediária interpretada.

Este MSIL é compilado just-in-time (JIT) pelo runtime para um assembly nativo na primeira execução, assim como um assembly regular. Você então usa uma expressão regular compilada da mesma maneira como você usa qualquer objeto Regex; a compilação simplesmente resulta em execução mais rápida.

No entanto existem alguns efeitos colaterais neste procedimento:

O método estático Regex.CompileToAssembly permite que você crie uma expressão regular compilada e a grave em um assembly externo.  Isso significa que você pode criar assemblies contendo conjuntos de expressões regulares, que você pode usar a partir de múltiplas aplicações. Para compilar uma expressão regular persistindo-a para um assembly basta seguir os procedimentos que iremos descrever a seguir:

Compilando uma Regex para um Assembly

A seguir temos as etapas para compilar uma Regex para um assembly:

  1. Crie uma matriz do tipo System.Text.RegularExpressions.RegexCompilationInfo grande o suficiente para conter um objeto RegexCompilationInfo para cada uma das expressões regulares compiladas que você deseja criar.
  2. Criar um objeto RegexCompilationInfo para cada uma das expressões regulares compiladas. Especifique valores para as suas propriedades como argumentos para o objeto construtor. A seguir estão as propriedades mais utilizadas :
    1. IsPublic, um valor booleano que especifica se a expressão regular gerada tem visibilidade pública;
    2. Name, um valor String que especifica o nome da classe;
    3. Namespace, um valor String que especifica o namespace da classe;
    4. Pattern, um valor String que especifica o padrão que a expressão regular irá corresponder;
    5. Options, um valor do tipo System.Text.RegularExpressions.RegexOptions que especifica opções para a expressão regular;
  3. Crie um objeto do tipo System.Reflection.AssemblyName e configure-o para representar o nome do assembly que o método Regex.CompileToAssembly irá criar;
  4. Execute o Regex.CompileToAssembly passando o array RegexCompilationInfo e o objeto AssemblyName;

Este processo cria uma assembly que contém uma declaração de classe para cada expressão regular compilada onde cada classe deriva de Regex. Para usar a expressão regular compilada contida no assembly, basta instanciar a expressão regular que você deseja usar e chamar o método como se você tivesse simplesmente criado com o construtor Regex normal.

Neste artigo eu vou mostrar um exemplo de como criar um objeto Regex que é compilado para o MSIL ao invés da forma intermediária usual.

Recursos usados :

Criando o projeto no VS Community

Abra o VS Community 2015  e clique em New Project;

A seguir selecione Visual C# -> Console Application;

Informe o nome Regex_MSIL e clique no botão OK;

A seguir defina o seguinte código no método Main() da classe Program.cs :

using System;
using System.Reflection;
using System.Text.RegularExpressions;
namespace Regex_MSIL
{
    class Program
    {
        static void Main(string[] args)
        {
            string mensagem = null;
            Console.WriteLine("Criando dois objetos Regex Compilados: PinRegex e CartaoCreditoRegex.");
            Console.WriteLine("Processando...");
            Console.WriteLine("");
            try
            {
                // Cria um array para tratar as informações do objeto Regex (definimos um array com tamanho 2)
                RegexCompilationInfo[] regexInfo = new RegexCompilationInfo[2];
                // Cria o RegexCompilationInfo para a expressão PinRegex
                regexInfo[0] = new RegexCompilationInfo(@"^\d{4}$", RegexOptions.Compiled, "PinRegex", "", true);
                // Cria o RegexCompilationInfo para o objeto CartaoCreditoRegex.
                regexInfo[1] = new RegexCompilationInfo(@"^\d{4}-?\d{4}-?\d{4}-?\d{4}$", RegexOptions.Compiled, "CartaoCreditoRegex", "", true);
                // Cria um AssemblyName  para definir um assembly de destino.
                AssemblyName assembly = new AssemblyName();
                assembly.Name = "MacorattiRegEx";
                // Cria a expressão regular compilada
                Regex.CompileToAssembly(regexInfo, assembly);
                mensagem = "Os objetos Regex - PinRegex e CartaoCreditoRegex - foram criados e compilados com sucesso ";
            }
            catch (Exception ex)
            {
                mensagem = ex.Message;
            }
            Console.WriteLine(mensagem);
            Console.ReadKey();
        }
    }
}

Este código irá criar o arquivo MacorattiRegEx.dll contendo as nossas expressões regulares - CartaoCreditoRegex e PinRegex - compiladas.

Executando o projeto iremos obter o resultado exibido a seguir:

Pegue o projeto completo aqui :   Regex_MSIL.zip

(Orou Jesus assim...) "E a vida eterna é esta: que te conheçam, a ti só, por único Deus verdadeiro, e a Jesus Cristo, a quem enviaste."
João 17:3

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Referências:


José Carlos Macoratti