Índice de la sección dedicada a .NET (en el Guille)
 
Espacios de nombres de .NET

Cómo se hizo...
Para los curiosos que quieran saber cómo estoy creando las páginas de los espacios de nombres

Publicado el 07/Dic/2004
Actualizado el 09/Dic/2004


Esto es para que sepas como me complico la vida para hacer lo que hago en este sitio, particularmente con esta sección que incluye los artículos publicados que contienen clases/tipos de los espacios de nombres de .NET Framework.

.


1- Averiguar los espacios de nombres de .NET Framework

Lo primero que tuve que hacer es saber qué espacios de nombres se exponen en .NET Framework, particularmente el de la versión 1.1.

Para ello empecé haciendo un programilla que averiguara el path del .NET Framework para abrir cada una de las librerías que hubiera en ese directorio.

Usando reflection leía cada una de las librerías y obtenía cada uno de los espacios de nombres que contuviera dicho ensamblado (el cual podía no ser un ensamblado de .NET).
Para que no se repitieran, cada espacio de nombre hallado lo guardaba en un elemento de una colección de tipo StringDictionary, elegí este tipo de colección porque sólo iba a guardar cadenas, así que el rendimiento se supone que sería mejor.
Aunque después lo cambié a una colección HybridDictionary, (aunque podría haber sido de tipo Hashtable), ya que también quise obtener los tipos de datos de cada espacio de nombres, la clave la guardaba en formato String y el valor realmente era una colección StringDictionary en la que guardaba cada uno de los tipos de ese espacio de nombres.
Esta segunda opción no la he usado, ya que eran demasiados datos y no era plan de complicarse demasiado... al menos por ahora.

Private espacios As New System.Collections.Specialized.StringDictionary

Finalmente hice la lista obteniendo información solamente de algunas librerías, que al fin y al cabo son las que realmente contienen todos los espacios de nombres de .NET Framework.
Esta es la asignación del array que contiene las librerías a examinar:

Dim paths() As String = { _
            "mscorlib", "System", "System.Data", "System.Design", _
            "System.Drawing", "System.Security", "System.Web", _
            "System.Web.Mobile", "System.Web.Services", _
            "System.Windows.Forms", "System.Xml" _
            }

Cada uno de los elementos del array los comprobaba en un método al que le pasaba el path del ensamblado a examinar:

For i As Integer = 0 To paths.Length - 1
    mostrarEspacios(CORUtil.dotNETPath & paths(i) & ".dll")
Next
Private Sub mostrarEspacios(ByVal ensamblado As String)
    ' mostrar los espacios de nombres del ensamblado indicado
    Dim asm As System.Reflection.Assembly
    Try
        asm = System.Reflection.Assembly.LoadFile(ensamblado)
    Catch 'ex As Exception
        Return
    End Try
    Dim tipos As Type() = asm.GetTypes()
    '
    For Each t As Type In tipos
        Dim s As String = t.Namespace
        If s <> Nothing AndAlso espacios.ContainsKey(s) = False Then
            espacios.Add(s, s)
        End If
    Next
End Sub

El contenido de los valores de la colección de tipo StringDictionary, lo asigné a un array de tipo String para poder clasificarlo.
Al array le asigné los valores, ya que en la colección de claves, se almacenan en minúsculas y quería que tuviera el mismo "case" que originalmente tenía.

Dim espaciosList() As String
ReDim espaciosList(espacios.Values.Count - 1)
espacios.Values.CopyTo(espaciosList, 0)
Array.Sort(espaciosList)

Después lo guardé en un fichero de textos para poder copiarlos y pegarlos en la página web.

Dim sw As New System.IO.StreamWriter("C:\espaciosNombres.txt")
For i As Integer = 0 To espaciosList.Length - 1
    sw.WriteLine(espaciosList(i))
Next
sw.Close()

 

2 - Averiguar las clases que contiene cada espacio de nombres

Como te comentaba, intenté hacerlo también usando Reflection, pero finalmente me decidí por hacerlo "por la cuenta de la vieja", es decir, usé la ayuda de Visual Studio .NET 2003 y copié y pegué.
Para ello busqué cada uno de los espacios de nombres, copié las clases, enumeraciones, etc., que mostraba la ayuda, la pegué en el editor de páginas Web (Front Page), convertí la tabla en texto normal y creé una lista con el tipo y la descripción.
Para acelerar este proceso (sobre todo por tedioso), el día 8 me creé una utilidad que generaba el código HTML que se muestra las clases, etc. que contiene cada espacio de nombres (generado a partir de lo copiado de la ayuda).

 

3 - Buscar los artículos que contienen las clases (y tipos) de cada espacio de nombres

El texto que obtuve en el punto anterior lo pegué en un editor de textos, eliminé las descripciones y me quedé sólo con las clases y tipos del espacio de nombres.
Esa "lista de tipos" la convertí en una sola cadena separada por puntos y comas, la cual usaría para buscar en cada uno de los ficheros de mi sitio que tuvieran algunas de esas palabras.

Cuando tengo que buscar algo en mis discos duros, suelo usar tanto el "buscador" de Windows como mi utilidad de Buscar y Reemplazar, aunque prefiero esta última, ya que algunas veces me encuentra más cosas que el buscador de Windows, pero tenía un problema: La utilidad de Buscar y Reemplazar sólo podía procesar un directorio a la vez y como máximo me permitía buscar dos palabras (o frases), así que tuve que modificarla para que aceptara más palabras (separadas por puntos y comas) y también más de un directorio (también separados por puntos y comas).
Esta utilidad, hecha en VB6, (puede que algún día me decida a pasarla a .NET), con las modificaciones indicadas es la que publiqué ayer, (el link anterior te llevará a la página con la última actualización).

Usando la utilidad ByR, le indiqué las palabras a buscar, le indiqué los directorios donde debía buscar (el de las colaboraciones de .NET y el "genérico" de .NET con mis artículos y cursos), seleccione que inspeccionara también los subdirectorios, que sólo tuviera en cuenta los ficheros con extensión HTM (no he comprobado ni los ASP ni los ASPX), y... ¡a buscar!

El resultado de los ficheros hallados, que contuvieran las palabras indicadas, los muestra en un ListBox, al que le he añadido un menú contextual para, entre otras cosas, poder seleccionar todos los elementos y poder copiarlos en memoria.
Esa lista de ficheros la pegué en un fichero de textos, le cambié los paths, (que hacían referencia al disco duro), de forma que fuesen paths relativos al directorio en el que está la página del espacio de nombres.
Guardé el fichero en formato texto.
Me hice otro programilla (de tipo consola) que leyera el fichero indicado y convirtiera esos paths en links utilizable y los guardé en otro fichero:

Dim sr As New StreamReader(args(0), System.Text.Encoding.Default)
Dim ficOut As String = Path.GetFileNameWithoutExtension(args(0)) & "_URL" & Path.GetExtension(args(0))
Dim sb As New System.Text.StringBuilder(CInt(sr.BaseStream.Length * 2))
While sr.Peek <> -1
    Dim s As String = sr.ReadLine()
    If s <> Nothing AndAlso s.Length > 0 Then
        sb.AppendFormat("<a href={0}{1}{0}>{1}</a><br>{2}", ChrW(34), s, vbCrLf)
    End If
End While
sr.Close()
Dim sw As New StreamWriter(ficOut, False, System.Text.Encoding.Default)
sw.WriteLine(sb.ToString())
sw.Close()

Abrí ese fichero y lo pegué en la página del espacio de nombres correspondiente, de forma que tuviese cada uno de los ficheros accesibles para poder abrirlos con el FrontPage.

Con fecha del día 8, este proceso lo automaticé, de forma que en lugar de crear los links para que después los pudiera ir comprobando, poniendo el título y el autor, lo he hecho para que lo haga medio automático.

Primero leo el fichero con los links de colaboraciones (colaboraNET), creo una colección StringDictionary (por aquello de que los datos se guardan como cadenas) con las páginas y en el valor guardo el título y nombre del autor separados con el carácter |:

Dim sr As StreamReader
sr = New StreamReader(ficColaboraNET, System.Text.Encoding.Default)
Dim colColabora As New System.Collections.Specialized.StringDictionary
Dim nombre As String = "", titulo As String = "", pagina As String = ""
Dim n As Integer = 0
'
While sr.Peek <> -1
    Dim s As String = sr.ReadLine()
    If s <> Nothing AndAlso s.Length > 0 Then
        If s.IndexOf("Colaboraciones del Año ") > -1 Then
            n = 1
        End If
        ' primero se encuentra el nombre
        If n = 1 AndAlso nombre.Length = 0 Then
            Dim i As Integer = s.IndexOf("Colaboración de ")
            If i > -1 Then
                Dim j As Integer = s.IndexOf("</", i)
                i += "Colaboración de ".Length
                nombre = s.Substring(i, j - i)
                titulo = ""
                pagina = ""
            End If
        End If
        If n = 1 AndAlso titulo.Length = 0 Then
            Dim i As Integer = s.IndexOf("<a href=""")
            If i > -1 AndAlso s.IndexOf("<a href=""http:") = -1 Then
                Dim j As Integer = s.IndexOf(""">", i)
                i += "<a href=""".Length
                pagina = s.Substring(i, j - i)
                j += 2
                i = s.IndexOf("</a>", j)
                If i = -1 Then
                    titulo = s.Substring(j).TrimEnd
                    s = sr.ReadLine
                    i = s.IndexOf("</a>")
                    If i > -1 Then
                        titulo &= " " & s.Substring(0, i).Trim
                    End If
                Else
                    titulo = s.Substring(j, i - j)
                End If
                ' guardar los datos
                If colColabora.ContainsKey(pagina) = False Then
                    colColabora.Add(pagina, nombre & "|" & titulo)
                End If
                '
                nombre = ""
                titulo = ""
                pagina = ""
            End If
        End If
    End If
End While
sr.Close()

 

Después examino cada uno de los ficheros y buscando en la colección, asigno el código HTML correspondiente, de forma que ponga el título y el nombre del autor. Si la página no está en el directorio de las colaboraciones, (o no está en la página de colaboraciones, por ejemplo, porque una misma colaboración tenga más de una página), busco dicha página, miro el título y si es una colaboración después tengo que poner el nombre del autor manualmente, en caso de que la página no esté en el directorio de colaboraciones, le asigno el nombre (el Guille), aunque, como tengo artículos publicados "fuera" del directorio de colaboraciones de Erik (el del curso de C#) y Unai Zorrilla, estos los tengo que asignar manualmente, pero como son pocos, pues no dan mucho la lata... je, je.
De esta forma, sólo tengo que comprobar las excepciones indicadas y los que no están "bien formados", ya que no siempre la gente manda los artículos como pido, así que...

Aunque el siguiente paso no lo he podido "automatizar", ya que esto no es fácil, sobre todo porque algunas clases tienen palabras "normales" o que son usadas como variables, así que...

 

4 - Comprobar que realmente los artículos tenía clases del espacio de nombres

Debido a que la utilidad de Buscar y Reemplazar no busca palabras independientes, sino que comprueba si la palabra indicada está en el texto aunque forme parte de otra palabra, por ejemplo File es una clase de System.IO, pero si la utilidad encontraba Filename, la daba por buena (no tuve ganas de modificar la utilidad para que buscase sólo palabras completas...), tenía que comprobar cada artículo para estar seguro de que realmente contenía las clases del espacio de nombres correspondiente.
Por tanto, abría cada artículo, comprobaba y si todo estaba OK lo añadía (realmente eliminaba los que no tenía palabras de ese espacio de nombres).
Como no era plan de dejar solo el link, copiaba el nombre del autor, lo pegaba junto al link, después copiaba el título del artículo y lo cambiaba en el link.

Y así cada vez, (aunque a la ahora de escribir este texto sólo he examinado dos espacios de nombres).
Por ejemplo, del espacio de nombres Sytem.IO, la utilidad ByR encontró 96 ficheros, pero realmente dejé 44.
Creo que tendré que añadirle a la utilidad de Buscar y Reemplazar que solamente busque palabras completas... así al menos me facilitará algo el trabajo, al menos el de tener que examinar el contenido de los artículos, aunque... como algunas veces simplemente se mencionan las clases, pero realmente el código del mismo no las utiliza, pues no se lo que haré...

 

Bueno y esto es lo que tengo que hacer para crear cada página de los espacios de nombres.
Ahora lo que queda por hacer es seguir "buscando" en el resto de espacios de nombres y después seguramente me "entretendré" en comprobar las clases que realmente se tratan en cada uno de esos artículos y así poder mostrar una información más exacta, todo para que te resulte más fácil encontrar lo que realmente necesitas... ¡espero que el esfuerzo valga la pena!

Por supuesto, espero que si eres uno de los colaboradores, te decidas a "aportar" tu ayuda a esta tarea, ¿cómo?, indicándome qué espacios de nombres y clases se tratan en tus artículos, tal como pido en "Lo Nuevo del 7 de diciembre de 2004".
Y si no eres colaborador y te quieres "entretener" en buscar info en los artículos publicados de .NET sobre los espacios de nombres y clases tratados en cada artículo, pues... deberías decírmelo antes para no duplicar el trabajo...
Si te vas a ofrecer a ayudarme, que no sea mucho después de Enero/Febrero de 2005, que si lo lees después de esa fecha, (como ha ocurrido en otras ocasiones), lo mismo ya no hace falta.
Gracias por adelantado.

Nos vemos.
Guillermo


la Luna del Guille o... el Guille que está en la Luna... tanto monta...