2012-08-11 21 views
5

Quiero hacer coincidir (seleccionar de un archivo de clase) nombre de método, nombre de propiedad y nombre de campo.C# regex - seleccione nombres de propiedades de clase, nombres de métodos y campos del archivo de clase (.cs)

Esta es la clase ejemplo:

class Perl 
{ 
    string _name; 
    public string Name { get; set; } 
    public Perl() 
    { 
    // Assign this._name 
    this._name = "Perl"; 
    // Assign _name 
    _name = "Sam"; 

    // The two forms reference the same field. 
    Console.WriteLine(this._name); 
    Console.WriteLine(_name); 
    } 
    public static string doSomething(string test) 
    { 
     bla test; 
    } 
} 

llegué código para los métodos:

(?:public|private|protected)([\s\w]*)\s+(\w+)\s*\(\s*(?:\w+\s+(\w+)\s*,?\s*)+\) 

y yo nos pregunta:

  • este código expresión regular anterior se lleva todos los métodos y se funciona bastante bien pero también quiero que seleccione el nombre del método pero sin parámetros y accesos. Así que desde la clase exaplmce usando mi resultado código será: Perl pública() y doSomething static (prueba de la cuerda) pero quiero ese tipo de resultado: Perl() y doSomething(). Por lo tanto, mi código coincide con el bueno pero quiero que el resultado se muestre como lo escribí en la frase anterior en I .
  • cómo seleccionar propiedades? con el resultado mostrado: tipo y propiedad nombre. Por lo tanto, a partir del resultado de clase exaple será: cadena Nombre
  • cómo seleccionar campos con resultado: escriba field_name. En caso de que fuera será: cadena _name
+1

puede estar duplicado de [esta respuesta SO] (http://stackoverflow.com/a/11647554/1495442) – Ria

+0

¿Podría tener sentido utilizar la reflexión en la clase compilada en lugar de regex en el archivo de código? Obtendrás resultados mucho más confiables (es decir, no tienes que preocuparte si tu comando de expresión regular cubre todos los casos posibles), y podría usarse con cualquier lenguaje .NET, no solo con C#. –

+0

así que obtuve una carpeta con archivos de clase .cs. ¿Puedo compilarlo "en el aire" y luego usar el reflejo? ¿Cómo compilar clases dinámicamente, por ejemplo, hay una función que puedo usar? por ejemplo. en el botón clic comile todos los archivos cs en la carpeta seleccionada? – born2fr4g

Respuesta

3

Utilice esta Regex

de métodos

(?:public\s|private\s|protected\s|internal\s)?[\s\w]*\s+(?<methodName>\w+)\s*\(\s*(?:(ref\s|/in\s|out\s)?\s*(?<parameterType>\w+)\s+(?<parameter>\w+)\s*,?\s*)+\) 

y lograr que los grupos nombrados methodName y parameterType y parameter.

y para campos:

(?:public\s|private\s|protected\s)\s*(?:readonly\s+)?(?<type>\w+)\s+(?<name>\w+) 

y obtener grupos nombrados type y name.

por ejemplo el código de métodos puede ser así:

var inputString0 = "public void test(string name, out int value)\r\nvoid test(string name, int value)"; 
foreach (Match match in Regex.Matches(inputString0, @"(?:public\s|private\s|protected\s)?[\s\w]*\s+(?<methodName>\w+)\s*\(\s*(?:(ref\s|/in\s|out\s)?\s*(?<parameterType>[\w\?\[\]]+)\s+(?<parameter>\w+)\s*,?\s*)+\)")) 
{ 
    var methodName = match.Groups["methodName"].Value; 
    var typeParameterPair = new Dictionary<string, string>(); 
    int i = 0; 
    foreach (var capture in match.Groups["parameterType"].Captures) 
    { 
     typeParameterPair.Add(match.Groups["parameterType"].Captures[i].Value, match.Groups["parameter"].Captures[i].Value); 
     i++; 
    } 
} 

Usted puede utilizar Irony - .NET Language Implementation Kit de CodePlex también.

+0

pero ¿y las propiedades y los archivos? ;) – born2fr4g

+0

¿qué pasa con el alcance de visibilidad 'interno'? –

+0

No puedo usar la ironía;). Estoy usando NET 2.0 en mi aplicación. Gracias por el código de expresiones regulares de campos. Intentaré modificarlo para que coincida con las propiedades (con get o set dentro de ** {} **) – born2fr4g

2

Como se indica en los comentarios a su respuesta, mucho más fiable método es compilar los archivos .cs y luego utilizar la reflexión para interrogar a los tipos para los miembros de su interés en ella participarán los siguientes:.

  1. Uso Compilador de C# (csc.exe) para compilar tus archivos. MSDN contiene examples and hints útil. Puede hacerlo manualmente o, si desea automatizar todo, puede ejecutar csc.exe programáticamente con Process class.
  2. Utilice el método Assembly.LoadFile() para cargar el conjunto resultante.
  3. Ahora puede emplear la reflexión a get types desde el ensamblaje y interrogate.

EDIT: Como alternativa a Csc.exe, podría utilizar CodeDOM - hay un example que contiene todo lo que necesita.

+0

Hace un tiempo, hice una pregunta similar sobre cómo obtener valores de parámetros usados ​​con el método mediante la reflexión, pero lamentablemente no hubo respuestas útiles. ¿Es eso posible? Porque esa sería la forma de ir en lugar de regex. – formatc

+0

@ user1010609 No veo cómo está relacionado con esta pregunta, pero publique el enlace y puedo echarle un vistazo. –

+0

No es relevante, pero digamos que quería hacer algo como esto 'Console.WriteLine (_name);', ¿hay alguna forma de obtener el valor de '_name'? Y si estaba codificado como 'Console.WriteLine (" John ");'? Debido a que Regex puede hacer eso con facilidad, pero hace otras cosas mucho más complicadas, solo quería apuntarlo en la dirección correcta. – formatc

0

Un lenguaje como C# acepta demasiadas variaciones en la sintaxis de sentencias para ser analizadas utilizando solo expresiones regulares. Además de las expresiones regulares, necesita un analizador gramatical contextual.

Me gustaría probar Roslyn: Es un compilador de C# cuyas partes internas son accesibles desde su código. Pídale a Roslyn que analice el código y lo consulte sobre cualquier información que necesite.

0

Sugiero mirar Microsoft.VisualStudio.CSharp.Services.Language namespace y otro Visual Studio Extensibility funcionalidad. Esto eliminaría la necesidad de compilar.

Cuestiones relacionadas