martes, 30 de julio de 2013

Conectar una aplicación .NET a una base de datos SQL Server

Vamos a conectar una aplicación de Visual Basic.NET a una Base de Datos SQL SERVER 2005 a través del Wizard que proporciona Visual Studio 2005 para conectarla con un DataSourceTambién daré nociones de otra forma de hacerlo que no desarrollaré. Finalmente haremos la misma operación pero por código

A través de DataSource

Continuando con nuestro  programa de ejemplo, sobre nuestro proyecto de Visual Studio 2005 (Visual Basic), añadimos un combo al formulario y procedemos del siguiente modo para enlazarlo a una tabla de nuestra base de Datos:

1.Añadimos los controles del componente Microsoft  remoteData Control 6.0



2. En la barra de herramientas aparece:


Elegimos BindingSource y colocamos sobre el formulario.


3. Para conectarla a la base de datos
Elegimos dataSource en el cuadro de propiedades del BindingSource y seguimos el Wizard.




Elegimos los parámetros de conexión que se corresponden con nuestra Base de Datos.




Ahora en la barra de herramientas aparecerán nuevas herramientas de Base de datos


4. En las propiedades del Combo añado la herramienta deseada (asociada a la tabla de la que deseamos leer los datos)





5. En ValueMember elegimos el campo a mostrar.


6. Para poder acceder al campo código de la tabla desde el código de Visual Basic podemos definir el campo deseado en las propiedades del combo.



7. Y después leerlo en el código de VB en el evento _SelectedIndexChanged

Private Sub CboHospitales_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
CboHospitales.SelectedIndexChanged


 Dim CodigoHosp As String
 CodigoHosp = CboHospitales.SelectedItem.Row.ItemArray(1)

También podemos ver su valor en tiempo de ejecución en la ventana watch



8. Finalmente ejecutamos la aplicación para ver que ha enlazado el campo de la tabla correctamente.


Podemos proceder del mismo modo con una caja de texto corriente.


Elegimos el objeto para la tabla y el campo deseados


Ahora al ejecutar el proyecto, cada vez que elegimos un hospital, aparece en la caja su dirección.


Para establecer el teléfono,  Colocamos sobre el formulario un objeto tbHospTelBindingSource y lo definimos


Colocamos una caja de lista y ponemos esto en sus propiedades:

Otra forma de conectarse: con SQL Datasbase

En proyecto, Add New Item



Se elige SQL Database


Conectar una aplicación Visual Basic.Net a una Base de Datos SQL Server 2005 mediante código

Para hacer lo mismo que se acaba de realizar pero por código, se procede del siguiente modo:
Creamos un módulo de conexión llamado conexion.vb e incluimos las siguientes líneas:

Módulo genérico de conexión

Imports System.Data.SqlClient
Imports System.Data
Module Conexion

    Public cnDB As SqlClient.SqlConnection
    Dim cmDB As SqlClient.SqlCommand
    Dim dsDB As DataSet
   
    Public Sub conectar(ByVal CadConectarSql As String)
        cnDB = New SqlClient.SqlConnection
        cnDB.ConnectionString = CadConectarSql
        Try
            cnDB.Open()
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

    Public Sub desconectar()
        cnDB.Close()
    End Sub

    Public Function conSelect(ByVal cadConsul As String) As DataTable
        Dim dtTabla As New DataTable
        Try
            cmDB = New SqlClient.SqlCommand(cadConsul, cnDB)
            dtTabla = New DataTable()

        Catch
            ' // MessageBox.Show(ex.Message);
        End Try
        Return dtTabla
    End Function

    Public Function conInsert(ByVal cadInsert As String) As DataTable
        Dim dtTabla As New DataTable
        Try
            cmDB = New SqlClient.SqlCommand(cadInsert, cnDB)
            cmDB.ExecuteNonQuery()
        Catch
            ' // MessageBox.Show(ex.Message);
        End Try
        Return dtTabla
    End Function
End Module

Para hacer uso de la conexión, en la clase form1 en el form1_load, hacemos uso del método conInsert para hacer un insert sobre la base de datos.

Para hacer un insert o un delete

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim CadConexion As String
       
      CadConexion = "User ID=sa;Initial Catalog=model;Data Source=SRV-      SERVIDOR\INSTANCIASQL2005;Password=xxxxxxx"
      Conexion.conectar(CadConexion)
      Conexion.conInsert("INSERT INTO dbo.tbHospital VALUES      ('HOS99','Prueba','Borrar 34')")

End Sub

O para una select

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim CadConexion As String     
Dim dt As New DataTable
Dim Valor As String

      CadConexion = "User ID=sa;Initial Catalog=model;DataSource=SRV-SERVIDOR\INSTANCIASQL2005;Password=xxxxxxx"

      Conexion.conectar(CadConexion)

Dim daDB As New SqlClient.SqlDataAdapter("SELECT * FROM dbo.tbHospital", Conexion.cnDB)

        daDB.Fill(dt)
        Valor = dt.Rows(2).Item(2)
        MessageBox.Show(Valor)
        Conexion.desconectar()
End Sub

O bien para conectar un Data grid a los resultados

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim CadConexion As String
Dim ds As New DataSet()

      CadConexion = "User ID=sa;Initial Catalog=model;Data       Source= SRV-SERVIDOR\INSTANCIASQL2005;Password= xxxxxxx"
      Conexion.conectar(CadConexion)

Dim daDB As New SqlClient.SqlDataAdapter("Select * From dbo.tbHospital", Conexion.cnDB)

      daDB.MissingSchemaAction = MissingSchemaAction.AddWithKey
      daDB.FillSchema(ds, SchemaType.Source, "Cust")
      daDB.Fill(ds, "Cust")

      DataGridView1.DataSource = ds
      DataGridView1.DataMember = "Cust"
       
End Sub

Explicación de la cadena de Conexión:

User ID=sa;  Usuario sa del SQL SERVER 2005
Initial Catalog=model;  Nombre de la Base de Datos
Data Source= SRV-SERVIDOR\INSTANCIASQL2005;  nombre de la instancia de SQL SERVER 2005
Password=xxxxxxx;  Password del sa del SQL SERVER 2005

En este enlace está la clase completa para conexión a base de datos.





miércoles, 24 de julio de 2013

Constructores de la clase


Conocimientos Teóricos


§ Qué es un constructor.
§ Tipos por valor y referencia.

Conocimientos Prácticos


§ Crear un constructor de una clase.
§ Crear un constructor con parámetros.
§ Manejar errores con un constructor.
§ Crear un array de instancias de clases.
§ Usar un array de instancias de clases como fuente de datos de un control ListBox.
§ Declarar e inicializar arrays.
§ Implementar el método ToString para una clase.

En un anterior artículo creamos una clase CHospital que incluía las propiedades, dirección, teléfono, etc. Cada vez que necesitamos crear una nueva instancia de la clase, se requieren varias líneas de código. Para hacer más fácil la creación de la instancia y simplificar el programa es posible crear un constructor de la clase que le permita ejecutar los tres pasos a la vez: declaración, instanciación e inicialización de los campos.

Qué es un Constructor


Un constructor es código que se ejecutará cuando se utilice la palabra clave new  para crear una instancia de una clase. Las atribuciones que tienen se pueden establecer en:

  § Un constructor puede validar los parámetros que se le pasan cuando se crea la clase.

  § Un constructor puede tener parámetros que le permiten inicializar los campos cuando
se crea el objeto.

  § Un constructor puede llamar a otro constructor para hacer parte de su trabajo.

  § Una clase puede tener varios constructores, tomando cada uno un conjunto diferente de
parámetros.

Un constructor sin parámetros se declara de esta manera:



Public Sub New ()

End Sub



El constructor se declara con la palabra clave pública Public. Se debe tener un constructor público para utilizar la palabra clave new o para crear una instancia de la clase.

Si no definimos ningún constructor en la clase, el compilador genera uno público sin parámetros, pero hay que asegurarse de que los campos de la clase se inicializan correctamente cuando se declaran.
También se puede declarar un constructor utilizando la palabra clave private. Si definimos un único constructor en la clase, y es privada, el código del cliente no será capaz de crear instancias de clases.

Tipos por valor y referencia


A continuación se describe la diferencia entre pasar un valor a una función o procedimiento por valor o por referencia.

Tipos


Todas  las variables son del tipo de referencia o por valor.

Una variable de tipo de valor se crea cada vez que declara una variable como



 § Un tipo entero (por ejemplo, Integer)

 § Un tipo doble  (por ejemplo, double)

 § Un booleano   (por ejemplo, Boolean)

 § Una  enumeración (por ejemplo, System)
 § Una estructura   (por ejemplo, DateTime)

Una variable de tipo de referencia se crea cada vez que declara una variable como
Una clase por ejemplo.


§ CHospital

§ Una interfaz
§ Una matriz (por ejemplo, Dim numeros() as Integer)

§ Un objeto (por   ejemplo, Dim x As Object)

§ Una cadena
§ Un delegado




La diferencia entre una declaración de una variable por valor o por referencia, es que la declaración por valor, asigna una ubicación de memoria a la variable completa, es decir, la ubicación contiene el valor de la variable. Mientras que en la declaración de una variable por referencia, la ubicación de memoria asignada contiene un puntero a la ubicación de la instancia de la clase en la memoria. De este modo las declaraciones por referencia sólo exigen una cantidad de memoria suficiente para apuntar a una instancia de una clase.

Dim m_hospital As CHospital

Cuando se crea una instancia de una clase a través del operador
New, se asigna memoria para los campos declarados en la clase. Estas expresiones provocan la asignación de memoria para el Teléfono, el Nombre, la Dirección  y el Número de Salas de la clase CHospital.

En la clase
CHospital. El operador New devuelve la dirección de la ubicación de los campos
la memoria.

m_hospital  = New CHospital("918483923", "Bravo Murillo 327.", 78, "De la Princesa")

Estas declaraciones, entonces, crean la instancia de la clase de CHospital y establecen en la  variable Un_hospital  la ubicación de la nueva instancia.
Por lo tanto, en el primer conjunto de estados, ¿Cuál es el valor de m_hospital antes de que sea establecido como en los últimos conjuntos de estados?
El valor de un tipo de referencia antes de que se inicialice es por definición Nothing. A continuación un fragmento de código que devuelve true:

Dim m_hospital As CHospital
MessageBox.Show((m_hospital Is Nothing).ToString())

Para comprobar el valor de los tipos de referencia Visual Basic proporciona la palabra clave is, También proporciona el método IsNothing  que permite probar el valor de la referencia. Devuelve el valor true si la referencia es Nothing. El siguiente código equivale al anterior:

Dim m_hospital As CHospital
MessageBox.Show((IsNothing(m_hospital).ToString()))

Cuando se intenta utilizar una referencia a una propiedad o método es Nothing, se produce un error. Dicho error se denomina System.NullReferenceException. La forma correcta de programar será comprobar si la referencia es Null o Nothing. Hay que tener cuidado al pasar la referencia al método como parámetro. Si es así, el código tendrá menos control sobre el estado de la variable antes de que sea pasado al método.


Una nueva  implementación de la Clase Hospital


En el artículo anterior, se establecían las propiedades  después de que se inicializa la clase. Esta vez, vamos a crear dos constructores diferentes para la inicialización de los campos de la clase. El primero, un constructor por defecto, crea una instancia exactamente como  se creó en el primer documento. El segundo constructor inicializa la dirección, el teléfono, el  nombre y el número de salas. Además, en lugar de crear una clase para cada teléfono, se guardarán  los teléfonos en una matriz simple. Se utilizará la matriz como la fuente de datos del control ListBox.


Creación de constructores de la clase CHospital




Se  modificará la clase CHospital con la adición de dos constructores y un método.


Cómo crear un constructor sin parámetros


1. Sobre la lista de nombre de la clase, elegir New.

Constructores de la clase


Se creará el siguiente código.

Public Sub New()
      m_telefono = ""
      m_direccion = ""
      m_nombre = ""
      m_num_salas = 0
End Sub

A continuación crearemos un constructor con parámetros. Se pueden crear múltiples constructores en una clase, entre ellos se distinguen por la lista de parámetros.

Añadir un constructor con parámetros


Al crear constructores con parámetros, recordar que cualquier código de un constructor
es ejecutado después de las inicializaciones de campos. Por lo tanto, puede anular cualquier inicialización de los campos previa.

2. Agregar el código siguiente después de las declaraciones de campo para declarar un
constructor con los parámetros: Teléfono y Dirección, Número de Salas y Nombre. No modificar el constructor existente, crear uno nuevo.


Public Sub New(ByVal telefono As String, ByVal direccion As String, ByVal numsalas As Integer, ByVal nombre As String)

End Sub

3. Agregar el siguiente código al constructor, para asegurarse de que ninguno de los campos
quedarán en blanco. Si alguno quedase en blanco saltaría una excepción en el programa, una excepción que detiene la ejecución del programa y evita que la clase cree una instancia.

Public Sub New(ByVal telefono As String, ByVal direccion As String, ByVal numsalas As Integer, ByVal nombre As String)

        If (telefono <> "") And (direccion <> "") And (nombre <> "") And (Not IsNothing(telefono)) And (Not IsNothing(direccion)) And (Not IsNothing(nombre)) Then
            m_telefono = telefono
            m_direccion = direccion
            m_nombre = nombre
        Else
            Throw (New Exception("Los campos Teléfono o Dirección o Nombre están vacíos."))
        End If
        If (numsalas <> 0) And (Not IsNothing(numsalas)) Then
            m_num_salas = numsalas

        Else
            Throw (New Exception("El campo Num salas está vacío."))
        End If

    End Sub

Si se elimina el constructor sin parámetros, el código del cliente se vería obligado a utilizar este nuevo constructor, lo que significa que ninguna instancia se puede crear sin Teléfono, Dirección, Número de salas o Nombre conocido.



Cómo utilizar un constructor para manejar errores


Si en los parámetros de entrada de un método o propiedad vienen como una cadena vacía, podemos manejar la situación de las siguientes formas:

  § Para que la sustitución del campo por una cadena vacía sea una decisión razonable, hay que  asegurarse de que los desarrolladores son conscientes de que cualquier instancia de CHospital puede contener una cadena vacía para el teléfono la dirección, nombre o cero para el número de salas. Se podría reemplazar el campo con una cadena vacía pero si se ha facilitado un constructor para forzar a que no haya cadenas vacías en los campos de teléfono, dirección, nombre y número de salas. No se debe recurrir a esta opción pues para ello se ha creado un constructor que establece las propiedades en la etapa inicial.

  § Se podría lanzar una excepción, En este caso, no se crea una nueva instancia de la clase  CHospital. La ejecución del programa se detendrá en la línea de código que contiene la palabra clave new. Se puede utilizar un bloque try (Prueba) para responder a un error.


Cómo usar los Constructores


A continuación se mostrará cómo reemplazar múltiples líneas de código con una llamada al constructor. También se creará una matriz para aprovechar las propiedades de enlace de datos de .NET mediante el uso de la matriz como un origen de datos.

Cómo crear una instancia de CHospital usando el constructor



En el form_Load se pone:

Dim Hospital1 As CHospital = New CHospital("918483923", "Bravo Murillo 327.", 78)

Tener en cuenta que cuando se escribe,
new, IntelliSense indica que tiene dos constructores definidos, como se muestra en la imagen siguiente.

Constructores de la clase


 Cuando hay más de un constructor, se dice que los constructores están sobrecargados.


Cómo crear un array de instancias de una clase


Se crean dos instancias de la clase CHospital y se añaden al array de instancias.

Dim Hospital1 As CHospital = New CHospital("918483923", "Bravo Murillo 327.", 78, "De la Princesa")

Dim Hospital2 As CHospital = New CHospital("918494324", "Santa Engracia 16.", 67, "Del Norte")

Dim m_hospitales As CHospital() = New CHospital() {Hospital1, Hospital2}

Se va a crear una matriz de teléfonos para cargar un ListBox en el formulario y  se creará una instancia de la clase CHospital con el constructor que tiene cuatro parámetros.

Pero en vez de crear manualmente las instancias del array de objetos de la clase CHospital, vamos a leer de la base de datos y cargarlo automáticamente, para ello hacemos:

Dim m_hospitales() As CHospital

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

'se crea un array de objetos de la clase CHospital
ReDim Preserve m_hospitales(0)
      
Dim dt As New DataTable
Dim Valor As String

      CadConexion = "User ID=sasorolla;Initial Catalog=model;Data      Source=SRV-SERVIDOR\INSTANCIA;Password=ae2di5rs"
      Conexion.conectar(CadConexion)

Dim daDB As New SqlClient.SqlDataAdapter("SELECT * FROM dbo.tbHospital", Conexion.cnDB)
Dim i As Integer

      daDB.Fill(dt)
      i = dt.Rows.Count

      'Este For carga un Array de Objetos CHospital con los valores de       la select de tbHospital mostrada arriba
      For i = 0 To dt.Rows.Count - 1
           
            ReDim Preserve m_hospitales(i)
            m_hospitales(i) = New CHospital()
            m_hospitales(i).Codigo = dt.Rows(i).Item(1)  'código
            m_hospitales(i).Nombre = dt.Rows(i).Item(2)  'nombre 
            m_hospitales(i).Direccion = dt.Rows(i).Item(3)  'Dirección
  
            Valor = dt.Rows(i).Item(2)  'Nombre del hospital
            ComboBox1.Items.Add(Valor)  'Se muestra en el combobox
      Next
End Sub

Cuando se ejecuta la aplicación, aparece un combox cargado con la lista de hospitales

Constructores de la clase


Queremos que al pinchar sobre uno de ellos, se cargue el resto de datos de cada hospital, y un listbox con los teléfonos. Añadir el siguiente código después de la declaración del array, como fuente de datos del control ListBox llamado ListTelefonos.

ListTelefonos.DataSource = m_hospitales

Cómo responder a selecciones en el control ListBox


Lo que se ve en el ListBox cuando se ejecuta la aplicación, son los  teléfonos de cada hospital.
Por que la fuente de datos del listbox es un array de instancias hospital, y cada objeto de la lista representa un hospital. En realidad podría mostrar cualquier dato (dirección, Nº de Salas)
Pero vamos a añadir código para que muestre los teléfonos.
Como los teléfonos no se encuentran en el array de objetos, hay que extraer de este, el código para hacer una nueva SELECT con el valor elegido en el combo anterior.
El Código completo se puede introducir en el evento  ComboBox1_SelectedIndexChanged
Quedando:

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged

        Dim Valor As String
        Dim i As Integer
        Dim dtable As New DataTable
        Dim strQuery As String

      strQuery = "SELECT strTelefono FROM dbo.tbHospital WHERE   strID_HOS = '" & m_hospitales(ComboBox1.SelectedIndex).Codigo &       "'"
Dim daDBTel As New SqlClient.SqlDataAdapter(strQuery, Conexion.cnDB)

      ListTelefonos.Items.Clear()  'borra los datos que hubiera        anteriormente en el list
      daDBTel.Fill(dtable)

      i = dtable.Rows.Count
      For i = 0 To dtable.Rows.Count - 1
            Valor = dtable.Rows(i).Item(0)  'Telefonos del hospital
            ListTelefonos.Items.Add(Valor) 'Rellena los teléfonos en              el listBox
      Next
TextDireccion.Text = m_hospitales(ComboBox1.SelectedIndex).Direccion

End Sub

El resto de campos, como la dirección del hospital, se pueden sacar directamente del array de Objetos.

TextDireccion.Text = m_hospitales(ComboBox1.SelectedIndex).Direccion

Finalmente el campo número de salas no se puede obtener directamente del Array de Objetos como.

LblNumSalas.Text = m_hospitales(ComboBox1.SelectedIndex).NumSalas

pues el dato está en otra tabla, y al poner el código de arriba nos muestra un 0 que es lo que carga el constructor.

Cómo declarar e inicializar Arrays



Se puede  elegir entre varias formas de declarar e inicializar un array de instancias de clase.

La sintaxis que se utilizó al principio  fue la siguiente:



Dim m_hospitales As CHospital() = New CHospital() {Hospital1, Hospital2}



Aquí hay otras formas de declarar la misma matriz:

Dim m_hospitales() As CHospital = New CHospital() {Hospital1, Hospital2}


Y otra forma

Dim m_hospitales() As CHospital = {New CHospital("918483923", "Bravo Murillo 327.", 78, "De la Princesa"), New CHospital("918494324", "Santa Engracia 16.", 67, "Del Norte")}


Y otra más:

Dim m_hospitales(2) As CHospital

m_hospitales(0) = New CHospital("918483923", "Bravo Murillo 327.", 78, "De la Princesa")

m_hospitales(1) = New CHospital("918494324", "Santa Engracia 16.", 67, "Del Norte")

Finalmente para mostrar el Número de salas de cada hospital, añadimos este código al evento
ComboBox1_SelectedIndexChanged.

'----------------Rellenar el número de salas--------------------------
dtable.Clear()
strQuery = "SELECT count(*) FROM dbo.tbSalaHos where strID_HOS ='" & m_hospitales(ComboBox1.SelectedIndex).Codigo & "'"

Dim daDBNumSal As New SqlClient.SqlDataAdapter(strQuery, Conexion.cnDB)

daDBNumSal.Fill(dtable)
LblNumSalas.Text = CStr(dtable.Rows(0).Item(1))

Quedando así el formulario al elegir un hospital.

Constructores de la clase



Agregar un método ToString



Anteriormente se utilizó el campo Teléfono como
string, para mostrarlo en su caja de texto.
Ahora utilizaremos una matriz para almacenar el Teléfono. De este modo se puede utilizar una matriz como una fuente de datos de un cuadro de lista, esto representa una ventaja respecto a la solución anterior. A continuación definiremos un método ToString de la clase de objetos que se desee mostrar. Así, un cuadro de lista puede utilizar el método ToString para mostrar cada uno de los objetos de la matriz.

Public Overrides Function ToString() As String
     Return m_telefono
End Function

La palabra clave Overrides, en la declaración del método indica que el código debe utilizar el método ToString que está definido en la clase CHospital, en lugar del método ToString definido en la clase System.Object del .NET. El método definido en System.Object lo único que hace es escribir el nombre de la clase. Hay que tener en cuenta que en .NET, todas las clases derivan de la clase System.Object

Resumen


Crear un constructor sin parámetros.

Public Sub New()
End Sub

Crear un constructor con parámetros. Crear un constructor sin parámetros y añadirle los que necesite, como si fuera un método de una clase.

Crear un array de instancias.

Dim hospitales() As CHospital

Crear e inicializar un array de instancias

Dim hospitales() As CHospital = {New Hospital(), New Hospital()}

Testear una  referencia para Nothing o Null.

Dim unHospital As CHospital

If IsNothing(unHospital) Then
‘ Añadir código aquí para tratar si viene a Nothing
End If


Un constructor complejo en C#

//****************************************
        //Constructor con un parámetro de entrada
        //inicializa todos los parámetros de entrada
        //inicializa un array de referencias que son todas nothing o null
        //el bucle while lee una línea del fichero utilizando un objeto StreamReader. Su método ReadLine devuelve nothing o null si es final de fichero.
        //la asignacion unalinea = lector.ReadLine () dentro del while devuelve el valor de unalinea, el cual es testeado directamente dentro del while.
        //Cada línea es testeada para averiguar el comienzo de la clase buscando las palabras "public class", este proceso es una vía simple para encontrar la declaración
        //de una clase pero no es exaustivo por que otros modificadores podrían preceder la palabra clave "class", para encontrar el nombre de la clase
        //el código busca la siguiente palabra despues de "class" usándo el método split.
        //la línea nombres = unalinea.Substring(comienzoNombre).Trim().Split(separadores); es un ejemplo de encadenamiento de llamadas a métodos. Cada método retorna una cadena,
        //de modo que se puede llamar a un método que retorna una cadena. Cuantas veces se realicen estas llamadas encadenadas depende de la legibilidad del código.

public Archivofuente(string RutaCompleta)
        {
            m_LineasDeCodigo = 0; //inicializa la variable
            m_NombresClase = new string[10];  //establece el array con una tamaño de 10 objetos
            m_ContadorClases = 0;
            m_RutaCompleta = RutaCompleta;  //inicializa la variable con el valor tomado de la propiedad

            try 
            {
                System.IO.StreamReader lector = new System.IO.StreamReader(m_RutaCompleta); //definimos un objeto lectura (Lector) de una clase del sistema y le asignamos el valor de la variable m_RutaCompleta
                int comienzoNombre;
                string unalinea;
                while ((unalinea = lector.ReadLine ()) != null//asigna los datos del objeto del sistema a la variable unalinea
                {
                    unalinea = unalinea.Trim();  //quita espacios en blanco a unalinea
                    //no cuenta espacios en blanco ni líneas de comentarios
                    if((unalinea != "") && (!unalinea.StartsWith("\\")))
                    {
                        m_LineasDeCodigo++;

                    }
                    if (unalinea.StartsWith("public class"))
                    {
                        comienzoNombre = unalinea.IndexOf("class") + 6;
                        char[] separadores = {' ','\t','{'};
                        string[] nombres = unalinea.Substring(comienzoNombre).Trim().Split(separadores);
                        string nombreClase = nombres[0].Trim();
                        m_NombresClase[m_ContadorClases++] = nombreClase;
                    }
                }
                lector.Close();

            }
            catch(System.Exception ex)  //aqui entra si hay error
            {
                throw new System.Exception("Problemas parseando el fichero fuente:" + ex.Message);
            }

        }

Y aquí la definición completa de la clase en C#.

namespace ProyectoCreacionPropiedadesMetodos
{
    public class Archivofuente
    {
        private string m_RutaCompleta;
        private int m_LineasDeCodigo;
        private string[] m_NombresClase;
        private int m_ContadorClases;

        //****************************************
        //Constructor con un parámetro de entrada
        //inicializa todos los parámetros de entrada
        //inicializa un array de referencias que son todas nothing o null
        //el bucle while lee una línea del fichero utilizando un objeto StreamReader. Su método ReadLine devuelve nothing o null si es final de fichero.
        //la asignacion unalinea = lector.ReadLine () dentro del while devuelve el valor de unalinea, el cual es testeado directamente dentro del while.
        //Cada línea es testeada para averiguar el comienzo de la clase buscando las palabras "public class", este proceso es una vía simple para encontrar la declaración
        //de una clase pero no es exaustivo por que otros modificadores podrían preceder la palabra clave "class", para encontrar el nombre de la clase
        //el código busca la siguiente palabra despues de "class" usándo el método split.
        //la línea nombres = unalinea.Substring(comienzoNombre).Trim().Split(separadores); es un ejemplo de encadenamiento de llamadas a métodos. Cada método retorna una cadena,
        //de modo que se puede llamar a un método que retorna una cadena. Cuantas veces se realicen estas llamadas encadenadas depende de la legibilidad del código.
        public Archivofuente(string RutaCompleta)
        {
            m_LineasDeCodigo = 0; //inicializa la variable
            m_NombresClase = new string[10];  //establece el array con una tamaño de 10 objetos
            m_ContadorClases = 0;
            m_RutaCompleta = RutaCompleta;  //inicializa la variable con el valor tomado de la propiedad

            try 
            {
                System.IO.StreamReader lector = new System.IO.StreamReader(m_RutaCompleta); //definimos un objeto lectura (Lector) de una clase del sistema y le asignamos el valor de la variable m_RutaCompleta
                int comienzoNombre;
                string unalinea;
                while ((unalinea = lector.ReadLine ()) != null//asigna los datos del objeto del sistema a la variable unalinea
                {
                    unalinea = unalinea.Trim();  //quita espacios en blanco a unalinea
                    //no cuenta espacios en blanco ni líneas de comentarios
                    if((unalinea != "") && (!unalinea.StartsWith("\\")))
                    {
                        m_LineasDeCodigo++;

                    }
                    if (unalinea.StartsWith("public class"))
                    {
                        comienzoNombre = unalinea.IndexOf("class") + 6;
                        char[] separadores = {' ','\t','{'};
                        string[] nombres = unalinea.Substring(comienzoNombre).Trim().Split(separadores);
                        string nombreClase = nombres[0].Trim();
                        m_NombresClase[m_ContadorClases++] = nombreClase;
                    }
                }
                lector.Close();

            }
            catch(System.Exception ex)  //aqui entra si hay error
            {
                throw new System.Exception("Problemas parseando el fichero fuente:" + ex.Message);
            }
        }
        //*****************************************************************
        //Definición de propiedades
        //propiedad de sólo lectura
        //Devuelve la ruta completa del fichero fuente
        //Esta líneas de abajo se muestran en IntelliSense
        /// <summary>
        /// Esta propiedad es de sólo lectura y devuelve una cadena con la ruta completa donde se encuentra el archivo de código fuente
        /// </summary>
        public string RutaCompleta
        {
            get { return m_RutaCompleta; }
        }
        ///<summary>
        ///Esta propiedad es de sólo lectura y devuelve el Nombre del archivo sin la ruta del archivo fuente
        ///</summary> 
        public string NombreArchivo
        {
            get
            {
                int ultimaBarra = m_RutaCompleta.LastIndexOf("\\");
                return m_RutaCompleta.Substring(ultimaBarra + 1);
            }
        }
        ///<summary>
        ///Esta propiedad es de sólo lectura y devuelve el número total de clases definidas en el código fuente
        ///</summary>
        public int CuentaClases
        {
            get { return m_ContadorClases; }
        }
        ///<summary>
        ///Esta propiedad es de sólo lectura y devuelve el número de líneas de código del fichero fuente, excluyendo líneas vacías y de comentarios
        ///</summary>
        ///
        public int LineasDeCodigo
        {
            get { return m_LineasDeCodigo;  }
        }
        //Fin Definición de propiedades
        //*****************************************************************
        //Definicion de métodos
        ///<summary>
        ///Definición del método ObtenerClase que devuelve uno de los nombres de las clases definidas en el fichero fuente, basado en un índice
        ///</summary>
        ///<param name="indice"> Índice basado en cero</param>
        ///<returns> Un nombre de clase</returns>
        public string ObtenerClase(int indice)
        {
            if (indice < m_ContadorClases) {
                return m_NombresClase[indice];
            }
            else
            {
                throw new System.IndexOutOfRangeException( m_ContadorClases + "Es la única clase definida.");
            }
        }
        //Fin Definicion métodos


    }
}



Related Posts Plugin for WordPress, Blogger...