Posts

Showing posts from September, 2010

Strong named assemblies in VB.NET y C++/CLI, C#

Spanish version / Versión en Español What's the use of having "strong named assemblies"? A strong name is unique. Therefore, if an assembly has a unique name, all types defined in it have a unique name as well. Assemblies without strong naming can only be found by the CLR if they are placed in the same directory as the referencing assembly or in special directories (like System32 or any other referenced by the PATH environment variable). A strong named assembly offers more possibilities (more on that in future posts). When an assembly is sought during runtime, its Name, Culture and Public Key Token are compared to see if there is a successful match. The assembly's version number is only taken into account in the comparison when the assembly has a strong name. This eases DLL Hell and encourages using version numbers for dlls. So that FxCop doesn't complain :P At least in Visual Studio 2008 is quite easy to have a VB.NET or C# class library

Strong named assemblies en VB.NET, C# y C++/CLI

Versión en inglés / English version ¿De qué sirve tener "strong named assemblies"? Un "strong name" es único. Así, si una assembly tiene nombre único, todos los tipos definidos en ella tienen nombre único también. Las assemblies con nombre débil sólo pueden ser encontradas si se las coloca en el directorio de la aplicación o en subdirectorios especiales (como System32). Las assemblies con nombre fuerte tienen más posibilidades (más sobre eso en próximos posts). Cuando se busca una dll en tiempo de ejecución, se comparan Nombre, Cultura y Public Key Token. El número de versión sólo se considera cuando la dll buscada es strongly named. Esto busca resolver el DLL Hell y proveer un sistema de versionado más sólido. Si la versión buscada no coincide, la dll no se carga. Para que el FxCop y sus amigos no rompan los quinotos :P Al menos en el Visual Studio 2008 es muy fácil hacer que un proyecto de VB.NET o C# genere una assembly con nombre fuerte

VB.NET: Raise base class events from a derived class

Spanish version / Versión en Español Say we: Have a class we want to divide into subclasses The future base class has events The refactoring leads us to the need of raising an event declared in the base class, from a derived class. When we try to do point 3, we will get a compile error saying that a derived class cannot raise events from a base class. To get around this, we add a protected method in the base class which encapsulates the RaiseEvent call, and call that method from the derived class using MyBase. This way: In the base class (parameters as needed): Protected Overridable Sub OnMessageGenerated(ByVal NewSender As Object, ByVal NewMessage As String) RaiseEvent MessageGenerated(NewSender, New MessageEventArgs(NewMessage)) End Sub And in the derived class: 'Do stuff 'Raise base class event MyBase.OnMessageGenerated( Me, "Message" ) 'Do more stuff... References: Mark Gilbert post

VB.NET: Lanzar eventos de la clase base desde una clase derivada

Versión en inglés / English version Supongamos que: Tenemos una clase que queremos desdoblar en subclases La futura clase base tiene eventos El refactoring nos lleva a la necesidad de que desde una clase derivada haya que hacer un RaiseEvent de un evento de la clase base. Cuando intentemos hacer lo indicado en el punto 3, nos surgirá un error de compilación diciendo que una clase derivada no puede lanzar eventos de la clase base. Para resolver esto, agregamos un método protected en la clase base que encapsule el RaiseEvent de marras, y en la clase derivada lo invocamos usando MyBase. Así: En la clase base (Los parámetros son a gusto nuestro): Protected Overridable Sub OnMessageGenerated(ByVal NewSender As Object, ByVal NewMessage As String) RaiseEvent MessageGenerated(NewSender, New MessageEventArgs(NewMessage)) End Sub Y en la clase derivada 'Hacer cosas... 'Quiero lanzar el evento de la clase base MyBase.OnMessageGenerated( Me, "Message" ) &

VB.NET: DoubleClick event for a Button

Spanish version / Versión en Español It's not everyday that you need to handle a double click event for a Button, but I happened to stumble upon a case. Suppose you have a Grid where the icons are buttons (in my case, those were image thumbnails, and so I intended to have the user double click a thumbnail in order to load the associated image). That led me to the need of handling the double click event for those Buttons. Now, .NET exposes the DoubleClick event for a Button, but it doesn't get fired for some obscure reason (Defined as a no-op?). Therefore, a workaround is to handle the more general MouseDown event instead, and consider the case where two clicks where made: Private Sub Button1_MouseDown(ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles Button1.MouseDown If e.Clicks = 2 Then MessageBox.Show("The button was double-clicked.") End If End Sub

VB.NET: Evento DoubleClick para un Button

Versión en inglés / English version No es normal tener que manejar un doble click para un Button, pero yo me topé con un caso donde es necesario. Supongan que tienen una Grid donde los íconos son Buttons (en mi caso, eran thumbnails de Imágenes, y quería hacer que con doble click se seleccionara la Imagen correspondiente al thumbnail). Eso me llevó a la necesidad de manejar el doble click para un Button. Ahora bien, .NET ofrece el evento DoubleClick pero no se dispara. Lo que hacemos entonces es manejar MouseDown y considerar el caso particular en que se hicieron dos clicks: Private Sub Button1_MouseDown(ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles Button1.MouseDown If e.Clicks = 2 Then MessageBox.Show("The button was double-clicked.") End If End Sub Referencias: MSDN Forum

.NET: Leak in Windows Forms

Spanish version / Versión en Español Consider this Windows Forms code: int i, j; for (i = 0; i < 150; i++) { for (j = 0; j < 200; j++) { this.Controls.Add(new Button()); } this.Text = String.Format("i={0}", i); this.Controls.Clear(); } You might need to change 150 and 200 to larger values for your system, but this code should eventually crash saying something like "Cannot create window handle". This is because the Clear() call does not instanltly release the Buttons. The GC should eventually do it, but he fails to do it on time. What's the cause for this? First of all, consider that Windows Forms is built on top of the Win32 API, so there is a message pump behind. Second, consider that in Win32, a window handle or any other graphic resource can only be destroyed by the thread who created it. Therefore, when the GC wants to destroy a Button, he must dispatch the call to the GUI thread. And he does it via the messag

.NET: Leak en Windows Forms

Versión en inglés / English version Consideremos este código dentro de un Form: int i, j; for (i = 0; i < 150; i++) { for (j = 0; j < 200; j++) { this.Controls.Add(new Button()); } this.Text = String.Format("i={0}", i); this.Controls.Clear(); } Tal vez haya que cambiar 150 y 200 por algo más grande en tu sistema, pero eventualmente esto explotará diciendo algo del estilo "Cannot create window handle". Esto es porque el Clear() no libera instantáneamente los botones; el GC debería hacerlo eventualmente, pero parece que no llega a tiempo. ¿A qué se debe esto? En primer lugar, debemos considerar que Windows Forms está montado sobre la API de Win32, así que detrás de esto hay un bucle donde se procesan mensajes (message pump). En segundo lugar, debemos considerar que en Win32, una ventana sólo puede ser destruida por el mismo thread que la creó. Por lo tanto, el Garbage Collector, al destruir los controles, debe despachar