# Ayuda C#. Usar objeto instanciado en un clase, en otra clase



## Gonzalonal (Oct 26, 2011)

Hola a todo. Gracias por leer.
Les cuento el problema. Tengo dos clases, en una de ellas instancio un objeto Socket, mediante el cual hago una conexion a una PC. Y en otra clase me gustaria usar exactamente el mismo objeto socket para enviar datos a la PC, sin tener que instanciar uno nuevo. Como puedo hacerlo?

En esta clase, esta el main, y es en la cual instancio el objeto socket, el cual tambien quiero utilizar en la clase de mas abajo, llamada logger.

```
namespace Client
{
    public class Program
    {
        public static void Main(string[] args)
        {
   
            IPAddress direc = Dns.GetHostEntry("host.dyndns.org").AddressList[0];
            IPEndPoint Ep = new IPEndPoint(direc, 12345);
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

            while (!socket.Connected)
            {
                try
                {
                    socket.Connect(Ep);
                }
                catch
                {
                }
            }

           Console.WriteLine("Conexion con server ("+Ep.ToString()+") satisfactoria");
        }
    }
}
```

clase logger

```
namespace Client
{
   public class logger
    {
        socket.send(Encoding.ASCII.GetBytes("hola")); // esto es lo que pretendo hacer y no puedo
     }
}
```


----------



## Pelelalo (Oct 26, 2011)

Gonzalo, poder se puede. No recuerdo bien cómo, pero lo que yo hice fué crear una clase Cliente (por ejemplo) y cuando tenía que hacer algo con ese objeto pues tenía que instar la Clase y luego el objeto, esto es; Cliente.Socket.

Pero como digo no recuerdo bien.


----------



## Dr. Zoidberg (Oct 26, 2011)

Solo hay dos formas de hacerlo: Una buena y una pésima.
*La buena:* crear una clase pública que opere según el patrón de diseño Singleton y que permita acceder a la instancia del socket a quien se la pida ===> Estudiar patron de diseño Singleton, que permite muchas cosas útiles adicionales.
*La pésima:* Hacer pública la referencia a la instancia del socket y accederlo desde cualquier parte prefijándolo con el nombre de la instancia de la clase que lo contiene, o con el nombre de la clase si es referencia estática ===> ver y descifrar lo que te dice Pelelalo


----------



## Chico3001 (Oct 26, 2011)

AAAHHHHH!!!! asi que para eso se usa el patron singleton..  creo que tendre que cambiar mi programa...


----------



## Gonzalonal (Oct 26, 2011)

Muchisimas gracias por ambas respuestas, me voy a informar un poco en el tema. Hago unas pruebas y dps les comento como me fue. Saludos!!


----------



## mnicolau (Oct 26, 2011)

Chico3001 dijo:


> AAAHHHHH!!!! asi que para eso se usa el patron singleton..  creo que tendre que cambiar mi programa...



Mmm yo también lo estaba haciendo de la forma "pésima" entonces , gracias por la info Eduardo 

Saludos


----------



## Pelelalo (Oct 26, 2011)

ezavalla dijo:


> *La pésima:* Hacer pública la referencia a la instancia del socket y accederlo desde cualquier parte prefijándolo con el nombre de la instancia de la clase que lo contiene, o con el nombre de la clase si es referencia estática ===> ver y descifrar lo que te dice Pelelalo



Supongo que te refieres a la seguridad.


----------



## Dr. Zoidberg (Oct 26, 2011)

Me alegro que les sea útil!
Este es un problema permanente que vengo viendo hace tiempo: se les enseña a programar usando un lenguaje O.O. y nunca se enseñan las miles de técnicas que han desarrollado y documentado los verdaderos especialistas del tema...y esas miles de técnicas están expuestas en los Patrones de Diseño. La conclusión es que siempre tienen que reinventar la rueda...SIEMPRE :enfadado:
Por desgracia, a esto solo pueden enseñarlo aquellos docentes que han usado los P. de D. en aplicaciones reales, por que no se aprenden con solo leerlos en un libro...y parece que no hay muchos de estos 

En la web debe estar el libro de Gamma y colaboradores...búsquenlo, bájenlo y páguenlo  y aprendan un montón de cosas super útiles, probadas, documentadas y desarrolladas por quienes saben mucho de esto...y también Microsoft  

PD: Si consiguen Patterns in Java, de Mark Grand (son dos volúmenes) les va a ser bastante útil, por que tiene un enfoque bastante pediátrico y con mucho apoyo de UML.

Saludos!



Pelelalo dijo:


> Supongo que te refieres a la seguridad.


Me refiero a las bases del paradigma de la Orientación a Objetos: Encapsulación (esta es la que se está violando), Herencia y Polimorfismo (y estas últimas no vienen al caso).
Violar la encapsulación tiene como efecto colateral reducir la "seguridad" en la gestión del código. Hay formas de violar la Encapsulación de manera "segura", pero como pocos saben como se hace...y eso no quita que se la esté violando....es mejor no aplicarla.


----------



## Pelelalo (Oct 26, 2011)

ezavalla dijo:


> Me refiero a las bases del paradigma de la Orientación a Objetos: Encapsulación (esta es la que se está violando), Herencia y Polimorfismo (y estas últimas no vienen al caso).
> Violar la encapsulación tiene como efecto colateral reducir la "seguridad" en la gestión del código. Hay formas de violar la Encapsulación de manera "segura", pero como pocos saben como se hace...y eso no quita que se la esté violando....es mejor no aplicarla.



Como ya te dijeron, gracias por tu gran aporte.


----------



## Gonzalonal (Oct 26, 2011)

Bueno, estuve investigando sobre Singleton, y sirve precisamente para lo que requiero.
Cito a Wikipedia:


> "El patrón de diseño singleton (instancia única) está diseñado para restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto.
> Su intención consiste en garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella"



El problema es que no se como implementarlo, soy realmente nuevo en C# pero tengo idea de programacion. Alguien me puede mostrar mas o menos como seria, con algun ejemplo super basico? 
Gracias


----------



## Chico3001 (Oct 26, 2011)

Como ya leiste en wikipedia lo que se hace es privatizar al constructor para que la clase no pueda ser creada por metodos convencionales, despues crear un metodo publico que al llamarlo revise si la clase ya esta creada y genere un error si se requiere


```
public class Singleton
{
    // Variable estática para la instancia, se necesita utilizar una función lambda ya que el constructor es privado
    private static readonly Lazy<Singleton> instance = new Lazy<Singleton>(() => new Singleton());
 
    // Constructor privado para evitar la instanciación directa
    private Singleton()
    {
    }
 
    // Propiedad para acceder a la instancia
    public static Singleton Instance
    {
        get
        {
            return instance.Value;
        }
    }
}
 
// Clase de prueba
public class Prueba
{
   private static void Main(string[] args)
   {
     //Singleton s0 = new Singleton();  //Error
     Singleton s1 = Singleton.Instance;
     Singleton s2 = Singleton.Instance;
     if(s1==s2)
     {
       // Misma instancia
     }
   }
}
```

Lamentablemente de C# no se mucho... lo ando aplicando en PHP5


----------



## Gonzalonal (Oct 26, 2011)

Gracias Chico3001. Mas o menos entiendo de que se trata. El tema es que la clase Socket no la hice yo.
Forma parte de "System.Net.Sockets". Es por eso que no puedo modificar sus contructores.
Yo simplemente quiero utilizar el socket instanciado en la clase "program", en la clase "logger" y no entiendo como implementar Singleton aplicado a esto. Muchas gracias y saludos


----------



## Dr. Zoidberg (Oct 26, 2011)

Te lo paso en Java...vos adaptalo a C#.

```
public class Singleton {

   private static Socket skt = null;

   private Singleton() {  /* Nada */  }

   public static Socket getSocket() {
      if( skt == null ) {
      // inicializar el socket
      }
      return skt;
   }

}
```
Es importante que la variable skt y el metodo getSocket sean de clase y no de instancia para asegurar la existencia de un solo socket.
Esto solo es un ejemplo y NO ES la mejor forma de hacerlo...pero bueno...se entiende la idea.

Ooopppssss...ya contestó Chico3001...eso me pasa por dejar lo compu sin terminar lo que estoy haciendo....


----------



## Gonzalonal (Oct 26, 2011)

Creo que termine de entender (duro el chico). De esta forma en cada clase que quiera usar el socket primero lo tengo que instanciar antes, y en lugar de crearse un objeto socket nuevo, se utiliza el creado en Singleton, correcto?. Les muestro el codigo a ver si lo aprueban o me sugieren algun cambio. Por el momento funciona.

Clase Singleton

```
namespace Client
{
    public class Singleton
    {
   
        private static Socket skt = null;

        private Singleton() {}

        public static Socket getSocket()
        {
            if (skt == null)
            {
                IPAddress direc = Dns.GetHostEntry("host.dyndns.org").AddressList[0];
                IPEndPoint Ep = new IPEndPoint(direc, 12345);
                skt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

                 while (!skt.Connected)
                {
                    try
                    {
                        skt.Connect(Ep);
                    }
                    catch
                    {
                    }
                
                }
                Console.WriteLine("Conexion con server ("+Ep.ToString()+") satisfactoria");
            }
            return skt;
        }
    }
}
```

Clase Program


```
namespace Client
{
    class Program
    {
     public static void Main(string[] args)
        {
            Socket skt = Singleton.getSocket();
            
   
            string strDataIn = "Hola!!\n";
            byte[] clientData = new byte[1024];

            clientData = Encoding.ASCII.GetBytes(strDataIn);

            skt.Send(clientData);

            skt.Close(); //[B][COLOR="Red"]Se cierra el socket por completo? o solo en esta clase? Gracias![/COLOR][/B]
            
        }
     }
}
```

Les agradesco mucho, funiona barbaro. Saludos!


----------



## Dr. Zoidberg (Oct 26, 2011)

Si cerrás el socket, como es el único que hay, se cierra para todos. Por eso te dije que no era la mejor forma de hacerlo....por que en realidad habría que aplicar un patrón Decorator para esconder el acceso al socket puro....pero eso requiere seguir estudiando.


----------



## Gonzalonal (Oct 26, 2011)

Gracias ezavalla. Me pasarias el nombre del libro de Gamma que mencionaste unos posts atras. Como lo ves para aprender C# teniendo medios conocimientos de c++?
Saludos y gracias


----------



## Dr. Zoidberg (Oct 26, 2011)

El libro de Gamma y colaboradores se llama "Design Patterns: Elements of Reusable Object-Oriented Software" y está escrito para C++... nada que ver con C#


----------



## Gonzalonal (Oct 26, 2011)

ezavalla dijo:


> El libro de Gamma y colaboradores se llama "Design Patterns: Elements of Reusable Object-Oriented Software" y está escrito para C++... nada que ver con C#



Aaaapaa, alguno de C# que me recomiendes para iniciarme?
Gracias


----------



## Chico3001 (Oct 26, 2011)

Es casi lo mismo... leyendo uno aplicas facilmente las tecnicas para el otro... 

O no?


----------



## Gonzalonal (Oct 26, 2011)

Posiblemente. Me parece que mas que enfocarme en C# deberia enfocarme mas en la POO. Saludos


----------



## Dr. Zoidberg (Oct 27, 2011)

Chico3001 dijo:


> Es casi lo mismo... leyendo uno aplicas facilmente las tecnicas para el otro...
> *O no? *


Depende que se trate...
Por ejemplo, C++ no tiene idea del concepto de "interface" que existe en Java y C#. Eso simplifica algunas cosas que en C++ hay que hacerlas con clases abstractas puras, pero como desconozco hasta donde sabe el autor del post...no sé si decirle que "son lo mismo"


----------



## Chico3001 (Oct 27, 2011)

Bueno... en lo personal siempre me ha gustado mas dominar el concepto y de alli aplicarlo a un lenguaje de programacion especifico.... Asi es mas facil saltar entre lenguajes....


----------



## Dr. Zoidberg (Oct 27, 2011)

Por supuesto que sí! Esa es la forma de hacerlo...


----------



## Chico3001 (Nov 13, 2011)

Cual seria el metodo correcto?

Heredar el patron singleton o volver a instanciarlo dentro de la clase que quiere usarlo?


----------



## Dr. Zoidberg (Nov 13, 2011)

El singleton no se hereda. Es una clase pública con un metodo publico y estático. Con llamar a este método se obtiene la instancia de la clase.


----------

