Buscar en este blog....

Mostrando entradas con la etiqueta C#. Mostrar todas las entradas
Mostrando entradas con la etiqueta C#. Mostrar todas las entradas

jueves, 30 de marzo de 2017

A tool with a fool, it's still a tool ;)

a tool with a foolTwo weeks ago a colleague came to me extremely happy, jumping like a happy Bunny to ask me if I could use the only license of NDepend that we have in the firm to get the metrics and the graphics of his new code he was proud of. Eight months back in time, we bought this tool, because I downloaded a trial version that I tried for... well, now I don't remember if it was 14 days or a month. But I was quite satisfied with it, so I asked to get a license. And I was listened. ;)

But the funny part of this story is that at that time, when I first tried it, this colleague came to me (this time not like happy Bunny) a told me "Good programmers don't need tools. I don't mean to offend you, but a fool with a tool, it's still a fool."... Now he's asking if he can get his own license too.

The interesting part of this, it's not in fact to say that "people who lives in glass houses should never throw stones", but to point out the motivational change that I noticed in this person. When he decided to throw his code in a metric tool, he also started thinking about how to write his code better. how to architect his solution, and taking care about dependencies, death code, etc.

NDepend DashboardSo, my conclusion is that when people see how good or bad his code actually is (in this case based on numeric metrics and graphics), they feel more motivated to do it better. Your quality doesn't live in the ether, you can actually see it! By the way, I must say that NDepend is a great tool, that I can fully recommend.

domingo, 24 de julio de 2016

Writing your first Aspect with Postsharp in C#

Hi!

As some of you might remember, some years ago I started to dabble in the world of Aspects Oriented Programming. I also wrote three posts explaining what is aspect oriented programming, what are its advantages and I gave an example on how to implement aspects in Java using AspectJ. That was a few years ago. Nevertheless, those posts are more relevant than ever!! So if you don't feel that sure with AOP, I´d recommend you to read a few on what aspects are to understand it before you continuing reading.

But life and likes started taking me to and through the .NET and C# world, so I began to look for new tools. Today there are really a lot of tools and frameworks to support aspects, however I chose the one called Postsharp.

Until now, I must admit that the simplicity of this framework seems wonderful for me when compared with other like Spring.NET AOP, which requires a little more of skills when setting it up. Postsharp doesn't need to be configured!! So this is the first advantage.

That said, let's go to the point and see an example on how this framework works.

Maybe the correct thing would be to start defining some concepts that I didn't clarify in those posts, and which are usefull to understand what we are doing. But no: today we start directly with an example. After that, in other posts, I will clarify these points.


So, lets imagine a very simple scenery. It's about a well-known and complex application called "Hello, World" ;), on which we are going to add an aspect. We are going to create only one aspect, that will be responsible to intercept the program's execution just before calling the method who writes "Hello World" in to the screen.

Step 1: Add Postsharp to the project.

Once we've created an empty project (e.g. Console Application), we add the Postsharp packet to it. The simplest way to do it is, of course, using NuGet. So easy as opening NuGet and searching the framework by its name. Then adding it to the project.

Here it is worth it to mention, that once added to the project, Postsharp asks the user to download an executable to be installed (version VS > 2010). This is meant to install a component that will added to Visual Studio. Postsharp has a free version which is enough to write aspects with total freedom, but it also has two more versions which are not only not free, but very expensive for the single user, but provide already-written and already-working aspects and also the possibility to write complex aspects. I haven't had yet the chance to try them, but I'm gonna do it as soon as possible. But do not be afraid of it: get the Express version (the free one) to continue. This installation needs to be made only once. So its not a problem.

Step 2: Write the "Hello World".

Actually, steps 1 and 2 are interchangeables. It is really the same. We can write first the "base" project (without aspects) and then install Postsharp.

I know it can be difficult, so I'm gonna help you. To create the "Hello World" project, you should call the method WriteLine() to write in the console, in the main class.

using System;

namespace FirstTryWithPostSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

I guess you didn't have much more complications in this step! ;) Let's move on!

Step 3: Write the Aspect.

Now the interesting part: an aspect, is nothing else but a class! Yes, that simple! Well.. but actually this class must accomplish two conditions:

  1. It must be ALWAYS serializable. This is achieved applying the "Serializable" attribute as we'll see soon..
  2. It ALWAYS inherits from one Postsharp's class, which give our class the "super powers", to put it in some way. They aren't actually superpowers, but these Postsharp's classes have methods which can be overridento redefine them. Postsharp's Core will insert them in our code during compile time. In our example, it will be inserted just before the call to Main() method.
Ok, lets create the class, which we can call AspectThatInterceptsAMethod and says this:



using PostSharp.Aspects;
using System;

namespace FirstTryWithPostSharp
{
    [Serializable]
    class AspectThatInterceptsAMethod : OnMethodBoundaryAspect
    {
        public override void OnEntry(MethodExecutionArgs args)
        {
            Console.WriteLine("Entering the method: " + args.Method.Name);
        }
    }
}


Briefly I want to say that I assume that we already know where this class is being indicated as Serializable, and that the aspect (the class) inherits from the class  OnMethodBoundaryAspect, which provides the possibility to rewrite some methods. In this case, we chose the method OnEntry() which indicates that whatever we do inside it will be executed just before executing the methods to which this aspect will be applied. But like OnEntry(), there are other methods that you can also redifne: OnExit(), OnSuccess() y OnException(). Lets see how to apply this aspect to the Main() Method.

Another little detail, is that args.Method.Name give us the name of the method that was intercepted. This, and much, much more (like accesing to the parameters, and its values) are part the powerful tools with which we count.

Step 4: Indicate to which methods our aspect will be applied.

So far we've made an aspect as god demands. But it is isolated, i.e. it is not being used! To use it, we just have to apply it as an attribute in the methods we want to be affected by it. This is made incredible easy in the following way:

 [AspectThatInterceptsAMethod]
        static void Main(string[] args)
        {


If we now run the project, we'll see that the aspect's text is showed at first, and then Main method's text. This occurs this way, because the aspect will be executed always before the method. Why? Just because we decided to overwrite the OnEntry() method. If we'd wanted to show the text before AND after the main's method, then we should have overwritten also the OnExit() method inside the aspect. Yes, only that!.

Another interesting tip is, that if we want the aspect to be applied to ALL methods of a class, it's just needed to put the attribute over the class name. Like this:

    [AspectThatInterceptsAMethod]
    class Program
    {

        static void Main(string[] args)
        {


And in this way, any method will be automatically a victim of our aspect ;) Easy, don't?

I invite you to try it by yourself!

This was an introduction to a very simple aspect. The aspects's world is very much extensive and interesting! Many wonderful things can be done but, however, like everything in software, I recommend you: always analyze which are the real advantages and disadvantages of introducing a new practice, framework or whatever. Aspects are not always needed. Remember: "Having a good hammer doesn't means that every problem is a nail".

In my experience, the use of aspects is a growing trend, but because many people is getting used to it and not being afraid of it. I'll try to come back with new things about Postsharp's aspects.

miércoles, 9 de marzo de 2016

C# - Obtener canales RGB de un Bitmap

Vamos a trabajar con el siguiente bitmap tomado de internet para trabajar:

 

Para descomponer un Bitmap de tres canales (RGB) en tres Bitmaps que representen cada uno, un canal del Bitmap original, podemos hacer lo siguiente:


rgb = new Bitmap("imagen.bmp");
int width = rgb.Width;
int height = rgb.Height;

Bitmap channelRed = new Bitmap(width, height);
Bitmap channelGreen = new Bitmap(width, height);
Bitmap channelBlue = new Bitmap(width, height);

for(int x = 0; x < width; x++)
{
   for(int y = 0; y < height; y++)
   {
      Color color = rgb.GetPixel(x, y);
      Color colorRed = Color.FromArgb(color.R, color.R, color.R);
      Color colorGreen = Color.FromArgb(color.G, color.G, color.G);
      Color colorBlue = Color.FromArgb(color.B, color.B, color.B);

      channelRed.SetPixel(x, y, colorRed);
      channelGreen.SetPixel(x, y, colorGreen);
      channelBlue.SetPixel(x, y, colorBlue);
   }
}

De esta forma, obtenemos 3 bitmaps, cada uno en blanco y negro y representando la tonalidad de cada canal:

 

Esto se ve así, porque ocupamos cada canal, de cada imagen, con el canal que obtuvimos previamente. Es decir, extrajimos el canal rojo de la imagen original, y grabamos todos los canales de channelRed con ese componente. Al tener cada canal el mismo valor, se ve gris. Si quisieramos que cada imagen contenga únicamente el valor del canal que extraemos, tendríamos que dejar los otros dos canales en cero. Cambiemos entonces la parte del código que asigna los colores:

Color color = rgb.GetPixel(x, y);
Color colorRed = Color.FromArgb(color.R, 0, 0);
Color colorGreen = Color.FromArgb(0, color.G, 0);
Color colorBlue = Color.FromArgb(0, 0, color.B);

Y lo que obtenemos es esto:


Si bien el resultado es el esperado, esta forma no es precisamente rápida. En caso de imágenes más grandes, el proceso tarda más, y más. Y ni hablar si queremos operar con estos valores. Hay, claro, formas de trabajar con esto mucho más rápido, en otro momento las veremos.

viernes, 31 de julio de 2015

Aspectos en C# con Postsharp (Un ejemplo muy simple)

Buenas!
Como algunos recordarán, hace unos años comencé a incursionar en el mundo de la Programación Orientada a Aspectos. En aquella época, hice tres entradas explicando qué es la programación orientada a aspectos, qué ventajas tiene, y hasta di un ejemplo de cómo implementarla en Java usando AspectJ. De eso hae ya unos años. Sin embargo, dichas entradas siguen más vigentes que nunca!! (Así que si no sabés muy bien lo que son y querés una introducción corta y clara, te recomiendo las dos primeras antes de seguir leyendo)

Sin embargo, la vida y los gustos me fueron llevando al mundo de .NET y C#, por lo que comencé a buscar nuevas herramientas. Hoy en día, hay realmente muchas herramientas y framworks para trabajar con aspectos. Sin embargo, yo preferí inclinarme al framework Postsharp.

Hasta ahora, admito me parece una maravilla la simplicidad de este framework comparado con otros, como Spring.NET AOP, que requieren un poquito más de maña con la configuración. Postsharp no necesita configurarse!!

Bueno, vamos al grano, y veamos un ejemplo de como funciona este sencillo framework.

Quizás lo correcto sería comenzar con algunas definiciones que no aclaré en los posts pasados, y que son de utilidad conceptual. Pero no: hoy comenzamos con un ejemplo, directamente. Después, en otro post aclararemos esos puntos.

Muy bien: vamos a suponer un escenario muy simple. Se trata de una compleja aplicación conocida como "Hola Mundo", a la cual le vamos a añadir un aspecto. Vamos a crear un solo aspecto que se encargue de interceptar la ejecución justo antes de ejecutar el método que escribe "Hola Mundo".

Paso 1: Agregar Postsharp al proyecto.

Una vez creado un proyecto vacío (por ejemplo, una consola), le agregamos el paquete de Postsharp. La manea más simple de hacerlo es, naturalmente, con NuGet. Tan simple como abrir NuGet y buscar el framework por su nombre. Luego agregarlo al proyecto.
Aquí vale aclarar, que una vez agregado al proyecto, Postsharp pide al usuario de descargar un ejecutable e instalarlo. (version VS > 2010). Esto es para instalar un componente agregado al Visual Studio. Postsharp tiene una versión gratuita que es suficiente para escribir aspectos con total libertad, pero también posee dos opciones más (que son pagas, y muy caras) las cuales proveen aspectos ya escritos y funcionando. Personalmente no he tenido el agrado de probar estas versiones aún. Pero sin miedo: instalá la versión Express (gratuita) para poder seguir. Esta instalación solo se realiza una vez.

Paso 2: Crear el Hola Mundo.

En realidad, los pasos 1 y 2 son intercambiables. Realmente es lo mismo. Podemos hacer primero el proyecto "base" (sin aspectos) y luego instalar Postsharp.

Para crear el proyecto "Hola Mundo", nada tan simple como en la clase principal hacer una llamada a la consola para escribir en pantalla

using System;

namespace PruebaPostSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hola Mundo!");
        }
    }
}


Este paso fue  fácil, no? ;) Sigamos!

Paso 3: Crear el Aspecto.

El aspecto es, nada más y nada menos, que una clase. Si así de simple. Bueno, es una clase con dos particularidades:

  1. SIEMPRE debe ser serializable. Esto se logra aplicando el atributo "Serializable" como ya veremos.
  2. SIEMPRE hereda de alguna clase padre proveniente de Postsharp, la cual le da los "poderes" de aspecto, por decirlo de alguna manera. En realidad, no son poderes, sino son clases que le permiten redefinir métodos (override) que ya tienen y que luego el core de Postsharp va ubicar en nuestro código. (Para nuestro ejemplo, lo ubicaría justo antes del llamado a "Main()".

Creemos una nueva clase, que se llame AspectoQueInterceptaUnMetodo y dice así:

using PostSharp.Aspects;
using System;

namespace PruebaPostSharp
{
    [Serializable]
    class AspectoQueInterceptaUnMetodo : OnMethodBoundaryAspect
    {
        public override void OnEntry(MethodExecutionArgs args)
        {
            Console.WriteLine("Entrado al método: " + args.Method.Name);
        }
    }
}

Brevemente quiero dar por sentado que ya sabemos donde esta indicado que la clase es serializable, y que el método hereda de la clase OnMethodBoundaryAspect, la cual le provee la posibilidad de reescribir algunos métodos. En este caso, elegimos el método OnEntry() que indica que lo que haga ese método se hará justo antes de ejecutar los métodos a los que se les aplica ese aspecto. Pero también hay otros: OnExit(), OnSuccess() y OnException(). Veamoslo en acción.

Otro detalle, es que en args.Method.Name tenemos almacenado el nombre del método que fue interceptado antes de llamar al aspecto. Esto, y mucho más (como acceso a los parametros, y los valores de los parámetros) son poderosas herramientas con las que podemos contar.
 

4) Indicar qué metodos serán afectados por el aspecto.

Hasta aquí tenemos un aspecto hecho y derecho. Pero está aislado: es decir, nadie lo usa. Para usarlo, solo debemos definirlo como atributo de el/los métodos a los que queremos que afecte.

De la siguiente manera:

 [AspectoQueInterceptaUnMetodo]
        static void Main(string[] args)
        {


Si ahora ejecutamos el proyecto, vemos que se muestra primero el texto del aspecto, y luego el del método Main. Esto es porque el aspecto siempre se ejecuta antes que el método. Si quisieramos que se ejecute después, deberíamos sobre escribir el método OnExit(). Si queremos que se ejecute antes y después, deberíamos sobreescribir ambos métodos: OnEntry() y OnExit(), y asi de simple funciona esto.

Otro tip interesante, es que si queremos que el aspecto se aplique a TODOS los métodos de una clase, solo basta con colocar el atriuto sobre la clase en cuestión:

    [AspectoQueInterceptaUnMetodo]
    class Program
    {

        static void Main(string[] args)
        {


Y de esta forma, cualquier método automáticamente será víctima de nuestro aspecto!! Simple, no?

Te invito a que pruebes vos mismo!

Esto fue una sencilla introducción a un aspecto muy simple. El mundo de aspectos es mucho más grande e interesante! Se pueden hacer cosas realmente estupendas pero, sin embargo, como todo en el software, siempre hay que analizar las ventajas y soluciones reales que esta (o cualquier otra) práctica puede conllevar. No siempre se necesitan aspectos.

En mi experiencia, el uso de aspectos es una tendencia que está creciendo, porque mucha gente está animándose a desarrollar con aspectos cada vez más gracias a los frameworks como postsharp, Spring.NET, etc Y si bien aún no es tan común, y aún no se lo práctica de la mejor forma, esto está cambiando de forma veloz, como todo en este campo.

Próximamente iremos mostrando cosas nuevas, más interesantes y más avanzadas!

Saludos!

viernes, 5 de junio de 2015

Web Service que recibe y devuelve JSON

La verdad es que si JSON se utiliza tanto hoy en día, decididamente su simplicidad de uso es uno de los factores más decisivos para esta tendencia.

Actualmente estoy haciendo unos Web Services en C# que deben ser consultados por un cliente enviando como request una cadena en formato JSON. Y no solo eso, el cliente también espera que el WS le devuelva su respuesta.. también en formato JSON.

Esto es, tremendamente simple de lograr. Para mostrar, voy a crear un proyecto muy simple. No será un WS porque no amerita la complicación. Quiero decir que lo que voy a hacer aquí se aplica a un WS o a un proyecto cualquiera... de hecho, voy a hacerlo para un método aislado.

Vamos a hacer una calculadora. Pero para darle un poco de "complejidad", vamos a hacer la calculadora reciba una lista de pares de números. Se tomarán los números de cada uno de estos pares y se los sumará. De forma que se devolverá una lista de "sumas". Por ejemplo:

Una lista para enviarle a la calculadora podría ser:
listaEntrada = [5,2],[1,-3],[-2,-2]
y la correspondiente lista de respuesta:
listaRepsuesta = 7,-2,-4

¿Estamos de acuerdo? Bien. Sigamos.

Si el Web Service va a recibir la lista de pares en formato JSON, debemos definir exactamente cómo.Podemos imaginar algo así:

{
    "pares": 
    [
  {
   "numero1":"5",
   "numero2":"2"
  },
  {
   "numero1":"1",
   "numero2":"-3"
  },
  {
   "numero1":"-2",
   "numero2":"-2"
  } 
    ]
}


y por lo tanto, la siguiente respuesta:

{  
   "sumas":[  
      7,
      -2,
      -4
   ]
}


Entonces, considerando esta decisión, vamos a armar dos entidades: una entidad para tener los datos de entrada, y otra entidad para poner los datos de salida. Las mismas podrían llamarse sumaRequest y sumaResponse, por ejemplo.

Escribamos estas entidades entonces, pero además agregamos una nueva: "Pares". Esta entidad, es el "tipo de dato" (por llamarlo de alguna manera) que contiene dos enteros, los cuales vamos a sumar.

public class sumaRequest
{
 public List<pares> pares { get; set; }
}


public class Pares
{
 public int numero1  { get; set; }
 public int numero2  { get; set; }
}


public class sumaResponse
{
 public List<int> sumas { get; set; }
}


Bueno, creando objetos de estas entidades y llenándolos con la información necesaria, ya podríamos trabajar perfectamente. LA operación suma, recibe la lista, y simplemente la procesa. Es decir, esto:

sumaResponse hacerTodasLasSumas(sumaRequest request)
{
 sumaResponse ret = new sumaResponse();
    ret.sumas = new List<int>();

 foreach(Pares pareja in request.pares)
 {
  int suma = pareja.numero1 + pareja.numero2;
  ret.sumas.Add(suma);
 }

 return ret;
}

Bueno, esto es muy lindo, pero aún no hemos metido a JSON en todo esto. Pero en realidad, es muy poco lo de tenemos que hacer. Solo hay que desserializar sumaRequest de un string que nos llegue, por otra parte serializar sumaResponse antes de devolverlo al usuario/cliente.

Para esto vamos a agregar el paquete JSON.NET desde Nuget (o la línea de comandos, como quieran). Una vez agregado, modificamos las entidades que directa o indirectamente entran en el JSON.
La diferencia entre entrar directamente o indirectamente, es simple: sumaRequest entra directamente, porque es la entidad que contiene la información del JSON de forma directa. Lo mismo ocurre con sumaResponse, que contiene la información directa que queremos almacenar. Sin embargo la entidad Pares entra de manera indirecta, ya que en realidad, debemos utilizar su contenido dentro del JSON, pero sólo por ser parte de la entidad sumaRequest.
Las entidades, las modificamos de la siguiente manera:

[JsonObject(MemberSerialization.OptIn)]
public class sumaRequest
{
 [JsonProperty(PropertyName = "pares")]
 public List<Pares> pares { get; set; }
}


[JsonObject(MemberSerialization.OptIn)]
public class Pares
{
 [JsonProperty(PropertyName = "numero1")]
 public int numero1  { get; set; }

 [JsonProperty(PropertyName = "numero2")]
 public int numero2  { get; set; }
}


[JsonObject(MemberSerialization.OptIn)]
public class sumaResponse
{
 [JsonProperty(PropertyName = "sumas")]
 public List<int> sumas { get; set; }
}


Lo que hemos hecho con el atributo JsonObject, es indicar que una clase forma parte de una Serializacion/Deserialización JSON (sin importar si es de forma directa o indirecta). Y con el atributo JsonProperty indicamos que el campo en cuestión debe ser serializado. Este atributo además permite especificar cómo se llama el campo cuando la información ser serializa/deserializa a JSON. Claramente, ambos nombres no tienen porqué coincidir.

Finalmente, y para terminar, debemos indicar en algun punto de código, que una string recibida debe deserializarse como entradaRequest, y que sumaResponse debe serializarse como salida. Esto lo hacemos con las funciones JsonConvert.DeserializeObject e JsonConvert.SerializeObject respectivamente. Nos queda así:

public string operacionDelWebService (string jsonRequest)
{
 sumaRequest objectRequest = JsonConvert.DeserializeObject<sumaRequest>(jsonRequest); // (1)

 sumaResponse objectResponse = hacerTodasLasSumas(objectRequest);    // (2)

 string response = JsonConvert.SerializeObject(objectResponse); // (3)

 return response;
}


Como vemos, la funcion -que podría ser la operación visible del WS- recibe y devuelve una cadena, ambas en formato JSON.

En (1) convertimos la cadena en formato JSON a objetos conocidos por nosotros (Deserializamos).
En (2) operamos normalmente con los objetos que conocemos.
En (3) convertimos la respuesta a un string con formato JSON. (Serializamos).

Luego se devuelve el string y todos contentos.
Espero que haya sido de utilidad y simple de entender.

Dejo el código completo funcional.


using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace Borrar02
{
    class Program
    {
        static void Main(string[] args)
        {

            string stringEntrada = " {\"pares\":[{\"numero1\":\"5\",\"numero2\":\"2\"},{\"numero1\":\"1\",\"numero2\":\"-3\"},{\"numero1\":\"-2\",\"numero2\":\"-2\"}]}";
            string stringSalida;

            WebService ws = new WebService();

            stringSalida = ws.operacionDelWebService(stringEntrada);
            
            Console.WriteLine("Respuesta del WS:\n{0}", stringSalida);
        }
    }

    class WebService
    {
        public string operacionDelWebService(string jsonRequest)
        {
            sumaRequest objectRequest = JsonConvert.DeserializeObject<sumaRequest>(jsonRequest);

            sumaResponse objectResponse = hacerTodasLasSumas(objectRequest);    // (2)

            string response = JsonConvert.SerializeObject(objectResponse); // (3)

            return response;
        }
        sumaResponse hacerTodasLasSumas(sumaRequest request)
        {
            sumaResponse ret = new sumaResponse();
            ret.sumas = new List<int>();

            foreach (Pares pareja in request.pares)
            {
                int suma = pareja.numero1 + pareja.numero2;
                ret.sumas.Add(suma);
            }

            return ret;
        }

        [JsonObject(MemberSerialization.OptIn)]
        public class sumaRequest
        {
            [JsonProperty(PropertyName = "pares")]
            public List<Pares> pares { get; set; }
        }

        [JsonObject(MemberSerialization.OptIn)]
        public class Pares
        {
            [JsonProperty(PropertyName = "numero1")]
            public int numero1 { get; set; }

            [JsonProperty(PropertyName = "numero2")]
            public int numero2 { get; set; }
        }

        [JsonObject(MemberSerialization.OptIn)]
        public class sumaResponse
        {
            [JsonProperty(PropertyName = "sumas")]
            public List<int> sumas { get; set; }
        }
    }
}

martes, 26 de mayo de 2015

Llamar a un Web Service desde un Plug-in de MS Dynamics

En este post vamos a ver como se hace para que un plug-in que hemos realizado nosotros mismos realice una llamada a un web service (que puede o no ser nuestro). Como siempre, estoy utilizando la versión de Dynamics 2015.
En este caso vamos a utilizar un web service que se pueda encontrar por Internet. Se trata de un conversor de unidades que encontré en la siguiente página:

http://www.webservicex.net/

El servicio en cuestión está en http://www.webservicex.net/ws/WSDetails.aspx?CATID=2&WSID=10, aunque si por algún motivo no se encuentra, no tienen más que buscar el servicio "Currency Convertor" desde la página principal. Ahora, si la página principal no funciona más, mala surte. Eso ya es algo que me trasciende.

Primero: Agregar la referencia al servicio.

Bien, primero lo primero: agregamos la referencia al servicio web haciendo click con el botón izquierdo sobre la carpeta "References" del proyecto, y después en "Add Service Reference".
Cuando se abre la vetana, vemos un cuadro de texto que dice "Adress". Bueno, allí vamos a copiar el WSDL del servicio.

El WSDL es un archivo XML que contiene el contrato del Web Service: qué hace, y con qué lo hace. Así podemos saber qué métodos tiene para ofrecernos, y qué parámetros requieren esos métodos. Ah, y también -lógicamente- que datos devuelven!
Para nosotros, esta URL es la siguiente:

http://www.webservicex.net/CurrencyConvertor.asmx?WSDL

Bien, una vez que ponemos la URL del WSDL del servicio que vamos a usar, le damos a "Go". Aparecerá una lista con los servicios que podemos utilizar. Abajo de la lista, hay una cuadro que dice "Namespace". Allí pondremos el nombre del namespace que "contedrá" el servicio después. Para nuestro caso, podría ser, por ejemplo: "WS_Curr" (que como habéis adivinado viene de "Web Service CURRency" ;)
Le damos aceptar.
Con esto, ya podemos usar los métodos y tipos que provee el web service sin que Visual Studio se enoje y lo subraye con rojo. La variable channel es la que está representando la instancia de nuestro web service.

Segundo: Instanciar el Web Service

Segundo lo segundo: creamos una factory utlizando un Endpoint y un Binding para crear canales de comunicación con el web service. En realidad, nosotros solo vamos a utilizar un canal.

BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Name = "CurrencyConvertorSoap";
myBinding.Security.Mode = BasicHttpSecurityMode.None;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

EndpointAddress endPointAddress = new EndpointAddress("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL");
ChannelFactory factory = new ChannelFactory(myBinding, endPointAddress);
CurrencyConvertorSoap channel = factory.CreateChannel();

Tercero (y último): Utilizar el servicio.

Esta es la parte más sencilla de explicar para mi, y entender para ustedes -o para mí si me olvido :)-
Para usarlo, se usa como se usaría cualquier método que está en otro namespace. Si queremos ver a cuantos pesos argentinos está el euro, no tenemos más que llamar al método adecuado, con los parámetros adecuados. Y en la segunda y última linea, mostramos una excepción desde el plug-in para ver si esto funcionó o no. He aquí:

double lalala = channel.ConversionRate(Currency.EUR, Currency.ARS);
throw new InvalidPluginExecutionException("No se si te interesa, pero el EURO está a: " + lalala.ToString());


Al ejecutarse este plug-in en MS Dynamics, deberíamos ver una excepción que mostrara el mensaje con el preciod el euro.
En definitiva, llamar a un web service desde un plug-in en Dynamics es algo extremadamente simple, como pueden ver. A continuación dejo el código completo del ejemplo, y sigue la promesa de en un próximo post mostrar como registrar un plug-in en Ms Dynamics.

using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace Plugin_Prueba
{
    public class Class1 : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));            
                                    
            BasicHttpBinding myBinding = new BasicHttpBinding();
            myBinding.Name = "CurrencyConvertorSoap";
            myBinding.Security.Mode = BasicHttpSecurityMode.None;
            myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
            myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

            EndpointAddress endPointAddress = new EndpointAddress("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL");
            ChannelFactory factory = new ChannelFactory(myBinding, endPointAddress);
            CurrencyConvertorSoap channel = factory.CreateChannel();

            double lala = channel.ConversionRate(Currency.EUR, Currency.ARS);
            throw new InvalidPluginExecutionException("No se si te interesa, pero el EURO está a: " + lala.ToString());
        }
    }
}


Saludos y bienvenidos los comentarios con buena onda -y sin spam!-

viernes, 22 de mayo de 2015

Escribir un Plug-In para MS Dynamics CMR 2015

Esta vez vamos  a escribir un poco de código. Hoy quiero mostrar cómo escribir un plug-in para ejecutar desde Microsoft Dynamics. Si bien yo estoy utilizando la version 2015, sirve para algunas anteriores, aunque desconozco exactamente hasta donde se aplica. Próximamente, en otra entrada del blog, voy a mostrar como registrar el plugin en MS Dynamics y asociarlo a algún evento particular.

Bien, la verdad es que crear un plug-in, en términos básicos, es muy, pero muy simple! De hecho vamos a comenzar con lo primero: agregar las referencias necesarias.

1. Primero lo primero.

Obviamente, comenzamos creando un proyecto. Este proyecto será simplemente una librería de clases (Class Library).

2. Agregar las referencias necesarias.

Lo segundo que tenemos que hacer es agregar las siguientes referencias:

  1. System.Runtime.Serialization
  2. System.ServiceModel
  3. Microsoft.Xrm.Sdk.dll
  4. Microsoft.Xrm.Client.dll
  5. Microsoft.Crm.Sdk.Proxy.dll

Las dos primeras se encuentran dentro de los ensamblados del framework. Las tres restantes debemos buscarlas dentro de la carpeta /bin de la carpeta descargada del "Dynamics CRM SDK".

3. Comenzar a escribir el plug-in.

Lo primero que vamos a tener en cuenta, es que la clase del plug-in debe implementar la interfaz IPlugin, el cual nos va a obligar a implementar el método Execute, cuyo código será ejecutado por el motor de ejecución de plug-ins dentro del CRM. En definitiva, tendremos esto:

public class Class1 : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {

        }
    }
Dentro de Execute escribimos nuestro plug-in. Por supuesto, podemos valernos de otras clases y métodos para implementar lo que querramos.

4. Firmar el Plugin

Este paso es escencial, de lo contrario ¡no podremos registrar el Plugin! Igualmente es fácil: Vamos a las propiedades del proyecto (Click izquierdo sobre el nombre del proyecto, y después en properties), y alli buscamos la pestaña "Signing". Checamos "Sign the assembly" y en "Choose a strong name key file" seleccionamos "New". Allí penemos un nombre cualquiera, pero SIN contraseña. Y listo, ya podemos compilar y registrar el plugin.

Trazas para la ejecución.

Bastante común es el caso de utilizar traces para hacer una traza de la ejecución. ¿Y ésto por qué? Porque un plug-in, como podréis imaginaros, es bastante difícil de debuggear. De hecho, la única forma es ejecutando es plug-in desde el CRM y mirando luego la traza de la ejecución. Para esto, creamos el servicio de traza con lo siguiente:

ITracingService tracingService;
tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));


y luego ir escribiendo algo que nos permita seguir la traza. Esto lo haremos llamando a:
tracingService.Trace("Paso 1");


Si intercalamos llamadas a tracingService.Trace("Paso X") dentro de nuestro código, podremos saber hasta dónde se ejecutó el plug-in. Si, por ejemplo falla, veremos que la traza nos muestras el lugar al que llegó antes de lazar la excepción. Acá muestro un ejemplo de traza:
using Microsoft.Xrm.Sdk;
using System;

namespace Plugin_Prueba
{
    public class Class1 : IPlugin
    {

        public void Execute(IServiceProvider serviceProvider)
        {

            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            tracingService.Trace("Paso 1");

            Entity entidad = (Entity)context.InputParameters["Target"];

            tracingService.Trace("Paso 2");

            if (entidad.Attributes.Contains("name") && entidad.Attributes["name"].ToString().Length > 5)
            {
                tracingService.Trace("Paso 3");
                throw new InvalidPluginExecutionException("Epa! El nombre tiene que tener más de 5 caracteres.");
            }
            tracingService.Trace("Paso 4");
        }
    }
}
Entonces, si durante la evaluación de la primera condición del if lanza una excepeción (si por ejemplo, el atributo "name" no existiera), se lanzará una excepción en el CRM y tendremos la opción de ver la traza. En la misma, figurara algo parecido a esto:
Paso 1
Paso 2
Pero no veremos "Paso 3" porque se lanzó la excepción y no se llegó a ejecutar esa parte. En la próxima entrada, veremos como registrar el plug-in para que el CRM lo pueda ejecutar. Es también algo muy sencillo.

Saludos!

viernes, 8 de julio de 2011

Error: Clase No Registrada.

Tenía un proyecto en .NET que en una máquina compilaba y corría sin problemas. Pero al querer pasar el proyecto a otra máquina, luego de compilar, me aparecía la siguiente excepción:

Clase no registrada (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))

La solución es simple: además de agregar las referencias al proyecto, debemos hacer click derecho (desde un adminsitrador de archivos) en los archivos DLLs que hemos referenciado, y luego click en "Registrar".

Con eso se soluciona el problema.

S2

sábado, 4 de septiembre de 2010

Ejemplo de uso del patron Observer

Ahora que hice el último patrón que se nos había encomendado implementar, el patrón Observador, voy a poner el ejemplo como hice con el patrón Command.

La idea es la siguiente: tenemos un caso de uso "Marcar Gol" que se dispara -imaginemos- cuando un sensor ubicado en un arco de fútbol detecta que pasa la pelota. Al dispararse este caso de uso, se llama al método de su experto anotarGol(), quien -entre otras cosas- llama al método actualizar() de SuscriptorGoles.

La interfaz del caso de uso "Ver Resultados" llama al método inciar() del controlador, con el cual éste se suscribe a SuscriptorGoles para que SuscriptorGoles llame al método actualizar() del controlador. Este método, lo implementa de la interfaz IObservadorGoles.

Notemos que SuscriptorGoles tiene un arreglo (o lista) de IObservadorGoles para actualizar a cada observador suscrtipto a el.

En el diagrama de clases olvidé especificarlo, pero conviene que SuscriptorGoles sea un singleton, ya que no vamos a usar más que una sola instancia de él.

Implementación en C#: Descargar

Salutes!

sábado, 28 de agosto de 2010

Ejemplo de uso del patron Command

Buenas, gente. Decidi subir este ejemplo al blog porque tuve que hacerlo para la facultad y por ahi viene bien ver algunos ejemplos, aunque que abunden en internet.
Como dije, se trata de un ejemplo aplicado del patrón Command a un negocio que tiene que ver con una escuela.

La idea es que cuando en dicha escuela se programan las fechas de exámenes, se debe notificar a los profesores, a los padres de los alumnos, a la Dirección General de Escuelas, y debe además, mostrarse en la cartelera. Es un caso ficticio, inventado para el ejemplo. La idea es que a los profesores se les debe enviar una notificación impresa a la casa, a los padres se les avisa por e-mail, a la DGE se le puede avisr por e-mail o por notificacion escrita (da igual). Digo que da igual, porque no me he centrado en el proceso particular de cada notificación en sí, sino solo en la aplicación del patrón Command.

Cuando el experto del caso de uso "Programar Fechas de Examenes" confirma dichas fechas, se debe proceder a hacer las notificaciones para cada caso. Eso es lo que está en el ejemplo.

El lenguaje utilizado es C#, con el IDE Visual C# 2008 Express Edition. Pueden descargar el código fuente y ver el diagrama de clases.

Código Fuente : Descargar
Diagrama de Clases: Descargar o la imagen.

Saludos!

jueves, 2 de octubre de 2008

Restar fechas en C#

Para comprobar el vencimiento de una fecha, es una buena idea usar la clase TimeSpan que provee la plataforma .NET. En mi caso, estoy usando la fecha de vencimiento del tipo DateTime, con lo cual en un princpio tuve problemas para hacer una resta de esa fecha con la fecha actual.

Foreando encontré varias propuestas que al menos a mi, no me funcionaron, ya que intentaban usar el metodo Substract de la clase DateTime, con un parametro DateTime; y esto no es posible porque -según mi compilador- no podia convertir DateTime en TimeSpan. Lo extraño, es que este metodo esta sobrecargado para aceptar ambos tipos de datos...

Pero en fin, una manera sencilla -y a mi gusto muy prolija- de hacerlo, es implementando un metodo al que podemos llamar, por ej, ObtenerDias y que le pasemos como argumento dos fechas (de tipo DateTime). Lo que nos devuleve es la diferencia en días entre dichas fechas. ( Obviamente, bien podría ser la diferencia en meses, años, segundos etc..)


public double ObtenerDias( DateTime Fecha1, DateTime Fecha2)
{
TimeSpan T1, T2;
double diff;

T1 = new TimeSpan( Fecha1.Ticks );
T2 = new TimeSpan( Fecha2.Ticks );

diff = ( T1.Substract(T2) ).TotalDays;

return diff;
}


La clase TimeSpan tiene la propiedad 'Ticks' como unidad de medida. Solo obtenemos los ticks de cada fecha, los restamos y mediante la propiedad TotalDays obtenemos la cantidad total de días entre ambas fechas. Logicamente se puede obtener TotalYears, TotalMinutes, etc.. Pero hay que tener cuidado con la propiedad 'Days' que no es lo mismo que 'TotalDays', ya que Days solo mide la cantidad de dias que corresponden al mes del año de la diferencia entre ambas fechas.. Por ejemplo:

si TotalDays = 35, entonces Days = 4 debido a que los 31 dias anteriores, corresponden al mes anterior y no se cuentan en el mes del ultimo de los 35 dias.

Me agradaría saber si esto les ha resultado de interés y si les ha servido. Saludos!

miércoles, 15 de agosto de 2007

Problema en MySQL desde .NET 2.0

Hola. Coméntoles que me encuentro actualmente desarrollando un proyecto bastante interesante para la H. Legislatura de Mendoza. Es un proyecto grande, pero yo sólo estoy en la parte de Software.

Como plataforma, estoy desarrollando en .NET, utilizando C#. La aplicación en cuestión, hace consultas frecuentemente (cada medio segundo aprox.) a la base de datos (MySQL).

En esta aplicación me conecto con un servidor de base de datos MySQL a través del conector oficial {MySQL ODBC 3.51 Driver}, la cadena de conexión que utilizo es:


DRIVER={MySQL ODBC 3.51 Driver}; SERVER=localhost; PORT=3306; DATABASE=dbint; UID=root; PWD=********;


Pero obtuve un gran error: Cuando dejo el programa corriendo (y por ende, haciendo consultas cada medio segundo), surge un error que dice:

ERROR [HY000] [MySQL][ODBC 3.51 Driver]Can't connect to MySQL server on 'localhost' (10048)

Esos errores que uno no tiene ni la más mínima idea por que aparecen. Busqué en algunos foros y una de las mejores respuestas, fue esta página. Igualmente, indagando solo, creo que el problema era que eso que yo llamo "una consulta" son en realidad, más de 100 consultas, y cada una en medio segundo. Supongo que la dB se caía por no soportar tanto tráfico. Supongo que era algo así como que las consultas se iban "superponiendo", es decir, se abrían nuevas consultas antes de cerrar las anteriores, y esto generaba el error.

Lo que hice (previo a conocer la existencia de esa web que linkee recién) fue aumentar el intervalo de tiempo de consulta a la base de datos a 1 segundo. El resultado fue notable: NO HUBO MÁS ERROR.

Igualmente, voy a volver a los 500ms de tiempo que tenía antes y probar la solución que propone la web, aunque estoy seguro que lo mejor es pegarle una revisada al código que hace las consultas y optimizarlo para evitar ese "revalsamiento" de consultas.


Saludos!

martes, 7 de agosto de 2007

Sobrecarga de Propiedades en C#

Buenas noches! La verdad que se hizo larga la espera de este primer posteo temático. El laburo me tiene medio a full, y sumado a la facultad se complica un poco.

Pero en fin, pasemos al tema que quería tratar.

Entiendo que conocen lo que son las propiedades de C#. Si no es así, recomiendo apreneder eso primero. Vemos que las propiedes pueden ser muy útiles.

Para seguir, sabemos que el compilador de C#, transforma las propiedades en métodos para mantener la compatibilidad con los lenguajes .NET que no las soportan.

Por ejemplo, si tenemos la propiedad siguiente:

public int NumeroPositivo
{
set
{
if(value >= 0)
num = value;
}
get
{
return num;
}
}

Lo que hace el compilador es generar algo como esto:

public set_NumeroPositivo(int value)
{
if(value >= 0)
num = value;
}
public int get_NumeroPositivo()
{
return num;
}

Entonces, como al fin y al cabo se generan dos métodos y la propiedad "se pierde" (por llamarlo de alguna manera), se me ocurrió que tal vez podría sobrecargar el método set_xxxx () para que se pueda cargar con diferentes tipos de valores. Para entender mi idea, les muestro como sería el proceso inverso:

Si tenemos los siguientes métodos:

public set_NumeroPositivo(string value)
{
if(value == "uno")
num = 1;
if(value == "dos")
nume = 2;

//... etc etc...
}
public set_NumeroPositivo(int value)
{
if(value >= 0)
num = value;
}
public int get_NumeroPositivo()
{
return num;
}

¡¡Mas allá de la poca funcionalidad que tenga esto!! Es solo un ejemplo, pero podría llegar a necesitarse usar algo asi. Bien, según esos métodos, nosotros podríamos pensar en que vienen de una propiedad. Es decir, realizamos el proceso inverso al que efectúa el compilador. Lo que podría llegar a quedarnos es lo siguiente:

public int NumeroPositivo
{
set
{
if(value >= 0)
num = value;
}
get
{
return num;
}
}

public string NumeroPositivo
{
set
{
if(value == "uno")
num = 1;
if(value == "dos")
num = 2;

//.. etc etc..
}
}

Digamos que para esta supuesta sobrecarga de propiedad, las condiciones serían:

* Que difiera el tipo de dato (en nuestro caso son int y string).
* Que no se implmente el bloque get en las sobrecargas.

Pregunté en muchos foros si era posible sobrecargar propiedades y me dijeron que no. Que usara métodos. Pero al fin y al cabo, usar métodos es volver al penúltimo código que mostré aquí. Bien, no se puede hacer entonces, pero ¡que bueno sería que se pudiera!

Me encotré con esta inquietud mientras revisaba un código medio feucho que tenía que re-codificar: Vi un método sobrecrgado que solo asignaba un valor a un campo privado. Y se podía tomar como enumeración o como string, pero al fin y al cabo era lo mismo. Y allí surgió mi pregunta.

Espero que no haya significado mucha pérdida de tiempo esto, debido a que es irrealizable. Solo quería mostrar la curiosidad.

Saludos.