Durante el día de hoy estuve dando una charla junto a Diego Gonzalez sobre las novedades de C# 4.0, .NET 4.0 Visual Studio 2010 en el marco del evento de Microsoft Run Reloaded.
La presentación la pueden bajar aca
Zaiden
El blog amigo del Nerd moderno
Durante el día de hoy estuve dando una charla junto a Diego Gonzalez sobre las novedades de C# 4.0, .NET 4.0 Visual Studio 2010 en el marco del evento de Microsoft Run Reloaded.
La presentación la pueden bajar aca
Para toda la gente que tenga un blog o similar y tenga que pegar código, le recomiendo que use el CopySourceAsHtml y a olvidarse de los problemas de Blogger, Word 2007 o Live Writer cuando pegás un pedazo de código!. (Gracias Mariano!)
Lo pueden bajar de aca.
Z
Hoy estábamos viendo con uno de los chicos del laburo que necesitaba poder acceder a distintos WebServices (desconocidos para el en tiempo de compilación) y queríamos encontrar una forma cómoda de hacerlo.
Después de buscar un poco, encontramos una solución que pareció bastante piola: usando el WSDL del WebService, generar la clase proxy en runtime y usar los WebMethods por Reflection. Está claro que no es la solución óptima en términos de velocidad, pero con unas clases helper que hice, resulta muy cómodo para usar.
El siguiente código lee el WSDL y genera la nueva clase en runtime:
try
{
//Get the web service description
Uri uri = new Uri(wsdlUrl);
WebRequest webRequest = WebRequest.Create(uri);
System.IO.Stream requestStream = webRequest.GetResponse().GetResponseStream();
ServiceDescription sd = ServiceDescription.Read(requestStream);
string sdName = sd.Services[0].Name;
//Create the ServiceDescriptionImporter
ServiceDescriptionImporter sdImporter = new ServiceDescriptionImporter();
sdImporter.AddServiceDescription(sd, String.Empty, String.Empty);
sdImporter.ProtocolName = "Soap";
sdImporter.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
CodeNamespace codeNamespace = new CodeNamespace(DefaultNamespace);
CodeCompileUnit compileUnit = new CodeCompileUnit();
compileUnit.Namespaces.Add(codeNamespace);
//Import the ServiceDescription
ServiceDescriptionImportWarnings warnings = sdImporter.Import(codeNamespace, compileUnit);
if (warnings == 0) //No warnings
{
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
codeProvider.GenerateCodeFromNamespace(codeNamespace, new StringWriter(), new CodeGeneratorOptions());
//Compile the assembly
string[] assemblyReferences = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
CompilerParameters param = new CompilerParameters(assemblyReferences);
param.GenerateExecutable = false;
param.GenerateInMemory = true;
param.TreatWarningsAsErrors = false;
param.WarningLevel = 4;
CompilerResults results = codeProvider.CompileAssemblyFromDom(param, compileUnit);
Assembly assembly = results.CompiledAssembly;
Type[] types = assembly.GetExportedTypes();
//Get the generated Type
return new DynamicProxyClass(types[0], GetMethodNames(sd.PortTypes[0].Operations));
}
else
{
throw new Exception(String.Format("Importing has warnings: {0}", warnings.ToString()));
}
}
catch (Exception ex)
{
throw new Exception("Couldn't generate proxy class (see inner exception)", ex);
}
Acá se puede ver que lo que devuelvo es una DynamicProxyClass. Esta clase lo que hace es wrappear la clase generada y exponer solo los métodos del WebService, sus tipos de retorno y sus parámetros.
Si les interesa jugar con esto, dejo para bajar el código completo de la solución.
Z
Les dejo la segunda parte del artículo, donde se ven más ejemplos y una implementación de Linq hecha sobre una clase propia.
Lo pueden bajar de acá.
¡Hasta la próxima!
Z
Hace unos meses, con Ariel Neisen y Javier Argüello hicimos un artículo explicando los nuevos features incluidos en C# 3 y Linq para publicar en la revista .Code. El artículo ya había sido enviado, sin embargo hace unos días nos enteramos de que la publicación de la revista fue suspendida (aparentemente for good). Como el artículo ya estaba hecho, decidí publicarlo en el blog.
La primera parte hace una introducción a las nuevas herramientas del lenguaje y a Linq. La pueden bajar de acá.
En un rato estaré publicando la segunda parte.
¡Hasta la próxima!
Z
Gente, para quienes quieran tener la última versión del Voice Commander que estoy haciendo, pueden bajárselo de http://www.codeplex.com/KeySimVoiceCommander
Saludos!
Z
Al parecer, lo que mostre en el post anterior funciona "como viene" nada mas con Windows Vista. Tendría que sentarme a ver bien que pasa sobre XP.
Saludos!
Z
En el post anterior vimos hace para usar el motor de reconocimiento de voz usando el .Net Framework 3.0 para reconocer las frases que nosotros queremos. Sin embargo, para hacer esto estábamos usando el motor de reconocimiento predeterminado del sistema. Haciendo un pequeño retoque, veremos que es posible usar el motor en cualquier otro idioma.
El primer requerimiento será bajar el MUI Pack del idioma que queremos usar. El Windows Vista Ultimate que yo tengo instalado trae ya instalado el motor para inglés americano y británico. Desde Windows Update, baje el MUI Pack de español y con esto, se instaló el motor de reconocimiento en español.
Como comenté en el post anterior, Windows no permite el uso del reconocimiento de voz en un idioma distinto al que se está usando en el sistema. Sin embargo, con las siguientes líneas de código es posible inicializar la clase SpeechRecognitionEngine con cualquier otro motor instalado.
Este ejemplo busca algún motor que esté en español y empieza a reconocer voz con el idioma elegido:
static void Main(string[] args)
{
SpeechRecognitionEngine sre = null;
foreach (RecognizerInfo config in SpeechRecognitionEngine.InstalledRecognizers())
{
if (config.Culture.TwoLetterISOLanguageName == "es")
{
sre = new SpeechRecognitionEngine(config);
}
}
Choices choises = new System.Speech.Recognition.Choices(
new string[] { "hola", "como", "estas", "mi nombre es Pablo" });
GrammarBuilder gb = choises.ToGrammarBuilder();
gb.Culture = sre.RecognizerInfo.Culture;
Grammar grammar = new Grammar(gb);
sre.LoadGrammar(grammar);
sre.SpeechRecognized += new EventHandler(sre_SpeechRecognized);
sre.SetInputToDefaultAudioDevice();
sre.RecognizeAsync(RecognizeMode.Multiple);
}
Debemos recordar que al inicializar el SpeechRecognitionEngine con un idioma distinto al predeterminado, también debemos cambiar la cultura del GrammarBuilder usado para generar la gramática a cargar. El resto del ejemplo es igual a lo ya visto.
Volviendo a nuestro objetivo de manejar cualquier cosa con la voz, lo que necesitamos hacer ahora es poder simular el uso de teclado.
Si bien el .Net Framework trae la clase System.Windows.Forms.SendKeys con el método Send, el cual recibe un String y simula presionar esas teclas, veremos que esto no nos va a servir para simular es uso del teclado en juegos que usen DirectX.
Para poder hacer esto, usé la función SendInput() desde C++ la cual está disponible al incluir el header windows.h . Esta función sirve para simular desde un nivel mas bajo el input desde teclado, mouse o algún otro dispositivo de hardware (más información en http://msdn2.microsoft.com/en-us/library/ms646310.aspx).
A continuación un pequeño ejemplo de cómo usarlo para simular la letra 'A'
void SimulateKeyboard()
{
KEYBDINPUT kb={0};
INPUT Input={0};
kb.wVk = 'A';
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
::SendInput(1,&Input,sizeof(Input));
}
Teniendo esto, creé un nuevo proyecto de DLL en C++ para poder exportarla y usarla desde código manejado.
Una vez obtenida la DLL que exporta el método creé un proyecto de DLL en C# para poder wrappear esta función y usarla cómodamente desde código manejado.
Con esto ya terminé de armar todas las herramientas necesarias para mi aplicación. Solo restó armar una aplicación que levante una configuración desde un archivo XML con las frases que quería decir, asociadas a las combinaciones de teclas a simular y listo! Ya tenía armado mi simulador de teclado manejado por voz.
Acá les dejo un link al código del proyecto entero para que lo bajen. Tengan en cuenta que esto lo hice medio a los apurones así que puede estar bastante buggeado, pero, como diría el Bambino Veira, La Base Está J
Saludos!
Z
Después de gastar horas y horas jugando al Star Trek: Bridge Commander, empecé a pensar que al juego le faltaba algo. En un perfecto simulador de una nave de Star Trek el capitán debería estar hablando con la tripulación de puente, y no picándole la cabeza (traducción al mundo real de hacer click al mirar hacia un tripulante) para que hagan lo que dice, por lo que me propuse lo siguiente: Hacer íntegramente en .Net una aplicación en la cual pueda reconocer comandos de voz, los mapee a hotkeys del juego y simule su uso, para que entonces yo pueda gritar: Red alert! Shields up! Y mi primer oficial levante los escudos y las armas, sin tener que memorizarme los 381273981 hotkeys que trae el juego.
Para lograr mi objetivo, empecé por donde suponía que iba a tener mayores dolores de cabeza: el Reconocimiento de Voz.
Desde hace unos días ya había estado entrenando al motor de reconocimiento de voz en ingles que trae Windows Vista, usando el (pésimo) micrófono incorporado a la laptop. A pesar de todo, el resultado había sido bastante satisfactorio, pudiendo usar con relativa comodidad la maquina mediante órdenes de voz, siempre y cuando este en un ambiente silencioso. La primera vez que instalé Windows Vista había bajado el MUI Pack en español, para poder tener reconocimiento de voz en ese idioma. El problema era que para poder usarlo desde Windows tenía que cambiar el idioma de toda la interfaz de usuario, cosa que prefería evitar, por lo que decidí no bajarlo esta vez.
Investigando en MSDN, encontré que con el Framework 3.0 viene un assembly llamado System.Speech, el cual tiene clases que sirven tanto para el reconocimiento como la síntesis de voz.
Si quieren usar este assembly en un proyecto de Visual Studio 2005 y no aparece en el listado de referencias para agregar, vayan a C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\ (o el equivalente en su máquina) y lo van a encontrar.
Dentro del namespace System.Speech.Recognition encontré las clases SpeechRecognitionEngine y SpeechRecognition, las cuales use para poder empezar a "escuchar" lo que estaba diciendo, dentro del programa (más información en http://msdn2.microsoft.com/en-us/library/system.speech.recognition.aspx).
A grandes rasgos, noté como diferencia de SpeechRecognition y SpeechRecognitionEngine que el primero levanta la aplicación que Windows Vista usa para reconocimiento de voz, por lo que todo lo que yo diga iba a ser "escuchado" por esta aplicación también; entonces si yo decía entre otras cosas "Open Internet Explorer" Windows iba a abrir el Internet Explorer, mientras que usando la clase SpeechRecognitionEngine, solo el motor de reconocimiento es activado, pero todo el control queda a manos del desarrollador.
A continuación, un pequeño ejemplo de cómo usé esta clase:
using System;
using System.Collections.Generic;
using System.Text;
using System.Speech.Recognition;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
SpeechRecognitionEngine sre = new SpeechRecognitionEngine();
Choices choises = new Choices(new string[] { "Hello", "Good bye" });
GrammarBuilder grammarBuilder = choises.ToGrammarBuilder();
sre.LoadGrammar(new Grammar(grammarBuilder));
sre.SpeechRecognized += new EventHandler(sre_SpeechRecognized);
sre.SetInputToDefaultAudioDevice();
sre.RecognizeAsync(RecognizeMode.Multiple);
Console.ReadKey();
}
static void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (e.Result.Confidence > 0.9)
{
Console.WriteLine("Escuché '{0}' con una certeza del {1}%",
e.Result.Text,
e.Result.Confidence * 100);
}
}
}
}
En el ejemplo se ve como creamos una nueva instancia de la clase Grammar, mediante el uso de la clase Choises, con la cual indicamos que es lo que vamos a querer escuchar desde el programa. Una vez creada la nueva gramática se la podemos agregar a la instancia del SpeechRecognitionEngine. A continuación suscribimos un método nuestro al evento SpeechRecognized para poder hacer algo cuando el SRE reconozca algo. Como el SRE puede escuchar no solamente de un micrófono, sino que también de un archivo de sonido, llamamos al método SetInputToDefaultAudioDevice() para que sepa de donde tiene que escuchar.
Para terminar, llamamos al método RecognizeAsync para poder empezar a reconocer voz de forma asincrónica.
El método sre_SpeechRecognized se fija que el reconocimiento tenga una certeza de más del 90% y en ese caso, escribe lo que reconoció en pantalla.
Con esto, ya tenemos la forma de reconocer los comandos de voz que le vamos a querer mandar a las otras aplicaciones. La próxima les voy a mostrar como poder elegir entre varios idiomas para usar en el reconocimiento de texto y como poder simular el uso de teclado en cualquier aplicación, incluso juegos que usan DirectX!
Saludos!
Z
Antes que todo, quiero aclarar que este texto no es mio, sino que es una traducción que hice de un excelente artículo que pueden ver aca: http://www.drivl.com/code.html
1. El código no se mueve
En las películas y en television el codigo siempre está navegando por la pantalla a increibles velocidades; está presentado como un flujo indecifrable de letras y números que tienen sentido perfectamente para el programador, pero imposible de comprender por cualquier otra persona. Entiendo que para la persona que no comprende, las habilidades de un programador pueden parecer increiblemente complejas, pero... honestamente, piensan que podemos leer mierda que no está quieta? Sería como tratar de leer seis diarios, volando en un tornado. Seguro, puedo ver como compila un kernel, tirar un tail de un log o, simplemente, ir viendo que tira el output de un programa - pero la mayoría de lo que puedo sacar de eso es cuando la ejecución frena y realmente puedo hacer scroll para arriba y ver que carajo pasó (excepto que el output haya ido suficientemente lento como para poder leerlo mientras salia)
2. El código no es texto verde sobre fondo negra
Seguro, puede ser texto verde sobre fondo negro si querés, pero la mayoría de los programadores usamos syntax highlighting y los sysadmins configuran su shell para usar colores ANSI
3. El código tiene estructura
Según las peliculas, todos los programadores odian las teclas space y enter. En el mundo real, el código tiene estructura - tiene saltos de linea, espaciado e indentación. Seguro que todos nosotros hemos escrito nuestra porcion de hacks ilegibles: yo solía escribir un montón y tenia la destreza de escribir horribles regular expressions que hicieron que varios de mis sucesores haga seppuku, pero esos días terminaron. Ahora es todo claridad.
4. El código no es tridimensional
Se acuerdan en Hackers cuando la Gibson era representada como una ciudad tridimensional, la cual los hackers tenian que navegar? Mierda! Nosotros usamos un poco de color en nuestro shell para hacer las cosas un poco mas claras, pero la última vez que chequee mi terminal no requería OpenGL. Estoy laburando! - No estoy jugando al Quake...
5. El código no hace "blip!" cuando va apareciendo en pantalla
Esto va para cualquier texto, no solamente código. Cuando el texto aparece en mi monitor no hace blips - Esto no es 1902 (o cuando sea que los monitores hacían eso). Esta es una de las mas comunes ofensas en las películas de Hollywood. En casi todas las películas donde hay una escena donde un personaje está escribiendo un E-Mail o navegando por Internet, el texto hace un blip cuando aparece. Se dan una puta idea de cuan irritante puede llegar a ser eso en la vida real? Este artículo solo serían unos treintamil blip!
6. El código no puede ser crackeado por un nene de 8 años en cuestión de segundos.
Lo lamento, pero simplemente no.
7. No todo el código está hecho para ser crackeado
Hollywood ama mostrar que la noción de programar, la encripción y la computación compleja en general son todo la misma cosa: una gran cantidad de datos secretos que tienen que ser rotos por un hacker realmente inteligente. Esto de alguna manera se puede llegar a entender ya que el término código es ambiguo. En el contexto de la computación, código tiene comunmente dos definiciones:
Hollywood comunmente usa la segunda para toda actividad desarrollada por un programador. No hay arrastre de ventanas, llaves que cierran IFs o escritorio. Todo en la computadora toma la forma de un mensaje encriptado, lo cual debe hacer ver porno un real quilombo.
8. El código no es simplemente 0100110 010101 10100 011
Seguro, cuando bajas al nivel binario es todo 1s y 0s, pero quien hace eso? Yo nunca conocí a nadie que codee en binario.
Hey directores de Hollywood: los programadores usan esa cosa bonita llamada Alfabeto. Tiene letras que podes juntar para formar palabras. Nosotros incluso ponesmos espacios entre esas palabras (ver #3)
Tambien, el chiste de que todo en una computadora son 1s y 0s se volvió dolorosamente no gracioso. Esta a la misma altua del chiste del usuario que usa la bandeja de su CD como posa-vasos. Estoy bastante seguro de que escuché es chiste mil veces por 1997. Solo por el hecho de que toda la data en una computadora es finalmente representada por unos y ceros no quiere decir que la base detras de eso es tan simple como un uno o un cero. Eso sería como decir que que toda la humanidad es un cacho de átomos de carbono (o de lo que sea que estamos hechos), asi que la próxima vez que alguien me robe el auto me puedo reír y decir "Uh! Esos tontos atomos de carbono..."
9. La gente que escribe código usa el mouse
Según Hollywood, la mayoría de los programadores no descubrieron como usar un mouse. Seguro, tipeamos rápido, pero el mouse es una herramienta muy util y no hay motivo para que lo abandonemos. Mientras disipamos estereotipos, también me gustaría decir que no todos los programadores son locos come-virgenes que juegan al World of Warcraft. Algunos de nosotros hacemos ejercicio y tenemos una vida social activa. Incluso, Algunos incluso han tenido sexo! Mierda!
10. La mayoría del código no es, necesariamente multiplataforma
Recuerdan en Independence Day, cuando el flaco matemático con cara de boludo escribe un virus que funciona tanto en su laptop apple como en la nave madre de lo aliens? Mierda que funciona!
Si la vida real fuese asi, yo podría portar wordpress a mi tostadora...
Alguna otra que se les ocurra?