Algo muy común a la hora de refactorear es que se elimine algún método o alguna clase, pero si estamos trabajando en un grupo de soluciones con referencias entre ellas, eliminar un método puede causar bastantes problemas… y molestias en quienes estén trabajando con nuestro código.
.Net ofrece una ayuda, es un atributo que se puede aplicar a clases, métodos, propiedades, variables y constantes y que sirve de alternativa para no romper compatibilidad, el attributo Obsolete() nos permite marcar como obsoleta una porción del código sin eliminarlo y nos brinda la posibilidad de mostrar un mensaje y generar una advertencia o bien un error a la hora de compilar.
Veamos un pequeño ejemplo en VB.Net y luego en C#
Public Class MiClase
<Obsolete("Este constructor fue reemplazado por New(String, Boolean)", True)> _
Public Sub New(Arg1 as String, Arg2 as String)
' Código del ctor obsoleto
' Ahora genera un error al compilar
End Sub
Public Sub New(Arg1 as String, Arg2 as Boolean)
'Código del nuevo ctor
End Sub
<Obsolete("Esta propiedad está obsolete. Por favor eliminar toda referencia a la misma antes del release 2.0")> _
Public ReadOnly Property IsObsolete() As Boolean
Get
Return True
End Get
End Property
End Class
class Ejemplo
{
[Obsolete()]
public const string MI_CONSTANTE = "NuevosProgramadores.com";
[Obsolete("No usar esta variable. Utilizar la variable FechaHoraActual en su lugar.", false)]
DateTime Fecha = DateTime.Now;
}
A simple vista se puede ver que la única diferencia entre su uso en VB.net y C# es que los atributos se aplican de manera diferente.
Por último veamos las 3 firmas de este atributo:
- Obsolete() - Genera una advertencia (warning) sin descripción alguna.
- Obsolete(String) - Genera una advertencia con con la descripción indicada en el parámetro.
- Obsolete(String, Boolean) - Utiliza el parámetro String como descripción y el Boolean indica si genera una advertencia (false) o un error (true).
}
Hoy alguien me preguntaba como mover todos los archivos encontrados en uno o más directorios usando el comando find y tenía una idea de como hacerlo, pero no tenía una máquina con Linux para probarla, en realidad es algo muy simple, en este caso moveremos todas las fotos encontradas en /home/nuevosprogramadores y todos sus subdirectorios a una nueva ubicación en /home/nuevosprogramadores/fotos y lo haremos con una sola línea.
$ mv `find /home/nuevosprogramadores -iname *.jpg ` /home/nuevosprogramadores/fotos
Ahora vamos a identificar las partes de ésta línea, primero el comando mv que se encarga de mover ficheros:
ahora el comando find, tal cual lo usamos:
$ find directorio-origen -iname nombre-archivo
Lo que hicimos fue concatenar ambos comandos, utilizando la salida del comando find como entrada del comando mv, para lo cual encerramos al comando find con las comillas simples: “ resumiendo, nuestro comando sería:
$ mv `find directorio-origen -iname nombre-archivo` destino
Una aclaración más, el parámetro iname se utiliza para buscar por nombre ignorando mayúsculas y minúsculas.
}
Muchas veces nos es útil capturar una imagen del momento en que se produce un error para saber qué sucedió o cómo solucionarlo. Sin ir más lejos, en mi trabajo anterior instalamos una aplicación y a veces teníamos un error que después de hacer guardias de 8hs frente a los usuarios no pudimos encontrar y las explicaciones y suposiciones de los usuarios carecían totalmente de sentido.
Por eso mismo muchas veces es bueno capturar el estado de la aplicación en el momento, en este ejemplo vamos a capturar una imágen de la ventana activa y la vamos a guardar.
Lo primero que haremos será la función que captura la imágen, para eso utilizaremos el viejo y conocido recurso de apretar la tecla PRINT SCREEN, y para eso utilizaremos la función SendKeys.Send.
Private Sub ImprimirPantalla()
SendKeys.Send("{PRTSC}")
GuardarImagenDesdeClipboard()
End Sub
Lo que hemos hecho hasta este momento es capturar la imagen, la misma queda en el portapapeles de Windows, así que para que nos sea útil necesitamos guardarla en un archivo debidamente identificado, para ello extraeremos la imagen del portapapeles y nos crearemos un archivo cuyo nombre se comprondrá de la fecha-hora actual y el nombre de la clase que generó la excepción.
Private Sub GuardarImagenDesdeClipboard()
If Clipboard.ContainsImage() Then
Dim NombreArchivo As String = String.Format("{0}_{1}.jpg", DateTime.Now.ToString("yyyyMMdd-HHmmss"), Me.Name)
Dim Path As String = String.Format("{0}\logs\imagenes\{1}", Application.StartupPath, NombreArchivo)
Dim img As Image = Clipboard.GetImage()
img.Save(Path)
End If
End Sub
Hay que tener en cuenta que para que la imágen se guarde es necesario que el directorio donde se va a guardar exista previamente, por eso sería conveniente chequear su existencia y si es necesario crearlo, antes de intentar guardar la imagen.
}
Más de una vez se puede dar una situación en la que necesitamos ubicar un form en determinada área de la pantalla, o redimensionarlo de acuerdo al tamaño de ésta, para eso necesitamos saber al menos el ancho y alto de nuestra pantalla, o sea la resolución de pantalla.
La función a continuación nos devuelve un String que contiene información útil acerca de la pantalla donde se está ejecutando la aplicación. Tomando esta función como ejemplo, se puede por ejemplo ubicar un form en la esquina inferior derecha de nuestra pantalla.
public String InfoPantalla(System.Windows.Forms.Control c)
{
// \r\n es salto de línea y \t es tabulador
return String.Format("Es Primario: \t{0}\r\nAncho: \t{1}\r\nAlto: \t{2}\r\nAncho útil: \t{3}\r\nAlto útil: \t{4}",
System.Windows.Forms.Screen.FromControl(c).Primary, // Devuelve True si se trata del monitor principal del quipo
System.Windows.Forms.Screen.FromControl(c).Bounds.Width, // Devuelve el ancho total de la pantalla
System.Windows.Forms.Screen.FromControl(c).Bounds.Height, // Devuelve el alto total de la pantalla
System.Windows.Forms.Screen.FromControl(c).WorkingArea.Width, // Devuelve el ancho útil de la pantalla, sin contar docks y taskbars
System.Windows.Forms.Screen.FromControl(c).WorkingArea.Height); // Devuelve el alto útil de la pantalla, sin contar docks y taskbars
}
}
La función recibe un objeto Control porque está pensaga para ser implementada en una clase, pero si la misma se implementa en un WindowsForm, o por qué no, un UserControl, Screen.FromControl() puede recibir directamente this como parámetro.
}
Hay varias formas de llegar al mismo resultado, la idea es obtener la ruta del directorio donde se está ejecutando nuestra aplicación, a continuación dejo 3 funciones que nos llevan al mismo resultado.
Para probarlas, basta con crear una nueva aplicación de consola, agregar las 3 funciones y llamarlas:
Sub Main()
Console.WriteLine(ObtenerDirectorio_1())
Console.WriteLine(obtenerDirectorio_2())
Console.WriteLine(obtenerDirectorio_3())
Console.Read()
End Sub
Function ObtenerDirectorio_1() As String
Return System.Threading.Thread.GetDomain().BaseDirectory()
End Function
Function ObtenerDirectorio_2() As String
Return Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\") + 1)
End Function
Function ObtenerDirectorio_3() As String
Return System.Reflection.Assembly.GetExecutingAssembly().Location.Substring(0, Application.ExecutablePath.LastIndexOf("\") + 1)
End Function
}