Programming Languages Hacks

Importanti regole per linguaggi di programmazione rilevanti come Java, C, C++, C#…

  • Subscribe

  • Lettori

    I miei lettori abituali

  • Twitter

Download Snapping / Sticky / Magnetic Windows for WPF

Posted by Ricibald on 19th October 2009

Starting from Sticky Windows on CodeProject (makes your windows snapping like winamp or google talk) I adapted the project developed for standard WinForm in Wpf Application. It works with multiple monitor and with windows vista/7.

DOWNLOAD LINK.

I adapted the following interface to get the app work with WPF App:

    public interface IFormAdapter
    {
        IntPtr Handle { get; }
        Rectangle Bounds { get; set; }
        Size MaximumSize { get; set; }
        Size MinimumSize { get; set; }
        bool Capture { get; set; }
        void Activate();
        Point PointToScreen(Point point);
    }

    public class WinFormAdapter : IFormAdapter
    {
        // Original Code Implementation
    }

    public class WpfFormAdapter : IFormAdapter
    {
        // My Implementation
    }

Enjoy and please give me feedback!

DOWNLOAD LINK.

Posted in .net, download | 12 Comments »

Reflection Ricorsiva di Oggetti Javascript

Posted by Ricibald on 5th March 2009

Spesso lavorando con javascript ci troviamo una variabile complessa di cui non sappiamo nulla. Sarebbe bello avere un autocompletamento che ci elenchi tutte le funzioni e le proprietà ma gli IDE per ora non ci vengono troppo di aiuto (se ne conoscete qualcuno ditelo!!).

Quindi risulta utile ispezionare la variabile per trovare tutte le proprietà e funzioni che questa variabile dichiara in modo ricorsivo. A questo scopo, riporto il codice che ho scritto che consente di fare questo “sporco lavoro”. Cosa ne pensate? Esiste modo di ottimizzarlo (a parte migliorie di output)?

function TraceMethodsAndProperties(obj) {
	var prefix = "";
	var result = TraceMethodsAndPropertiesRecursion(obj, prefix);
	copyToClipboard(result);
}

function TraceMethodsAndPropertiesRecursion(obj, prefix){
	//alert('gotta:' + prefix);
	var result = "";
	try {
		if(obj != null) {
			for (var s in obj)
			{
				var value = obj[s];
				var key = prefix + s;

				result += "---------" + key + '=' + value + ';\n\n'
				var newPrefix = key + '.';
				result += TraceMethodsAndPropertiesRecursion(value, newPrefix);
			}
		}
	} catch(e) {
		// eccezione affogata per il singolo elemento che non consente la scansione: vai al prossimo
	}
	return result;
}

function copyToClipboard(s)
{
	window.clipboardData.setData('Text', s); // solo IE
}

Esempio di utilizzo:

    var persona = getCarloRossi();
    TraceMethodsAndProperties(persona);
    // OUTPUT:
    // ---------Nome=Carlo
    // ---------Cognome=Rossi
    // ---------Indirizzo.Via=via roma
    // ---------Indirizzo.Civico=32
    // ---------Indirizzo.CheckValid=function checkValid(via) { return via != ""; }

Posted in javascript | 2 Comments »

Certificazione MCTS Web verso l’MCPD Enterprise Framework 2.0 – Parte 3/5: 70-528

Posted by Ricibald on 19th February 2009

Questa è la terza parte (vedi la seconda parte) di una serie di pdf che ho scritto per riassumere il contenuto delle certificazioni Microsoft che portano alla certificazione Microsoft MCPD di livello “enterprise” (Distributed).

Logicamente questi pdf li avevo creati per riassumere i concetti che io ritenevo importante riassumere. Potrebbero essere appunti che non vi interessano affatto o che reputate inutili. Viceversa potrebbe essere un’ottima integrazione e un’ottimo punto di partenza per ripassare quanto studiato sul libro ufficiale dell’esame.

TS: Microsoft .NET Framework 2.0 – Web-Based Client Development

Posted in .net | No Comments »

Certificazione MCTS Win verso l’MCPD Enterprise Framework 2.0 – Parte 2/5: 70-526

Posted by Ricibald on 18th February 2009

Questa è la seconda parte (vedi la prima parte) di una serie di pdf che ho scritto per riassumere il contenuto delle certificazioni Microsoft (vedi terza parte) che portano alla certificazione Microsoft MCPD di livello “enterprise” (Distributed).

Logicamente questi pdf li avevo creati per riassumere i concetti che io ritenevo importante riassumere. Potrebbero essere appunti che non vi interessano affatto o che reputate inutili. Viceversa potrebbe essere un’ottima integrazione e un’ottimo punto di partenza per ripassare quanto studiato sul libro ufficiale dell’esame.

TS: Microsoft .NET Framework 2.0 – Windows-Based Client Development

Posted in .net | 1 Comment »

Certificazione MCPD Enterprise Framework 2.0 – Parte 1/5: 70-536

Posted by Ricibald on 17th February 2009

Questa è la prima parte di una serie di pdf che ho scritto per riassumere il contenuto delle certificazioni Microsoft (vedi seconda parte) che portano alla certificazione Microsoft MCPD di livello “enterprise” (Distributed).

Logicamente questi pdf li avevo creati per riassumere i concetti che io ritenevo importante riassumere. Potrebbero essere appunti che non vi interessano affatto o che reputate inutili. Viceversa potrebbe essere un’ottima integrazione e un’ottimo punto di partenza per ripassare quanto studiato sul libro ufficiale dell’esame.

Esame Microsoft 70-536: TS: Microsoft .NET Framework – Application Development Foundation

Posted in .net | No Comments »

Troncare valori Decimali Assimilabili ad Interi: Automatizzare Modifiche di Proprietà in una Classe

Posted by Ricibald on 1st February 2008

Lo so, il titolo dice poco e dice troppo… Cerco ora di spiegarvi la cosa, e credo che possa interessare a tutti gli sviluppatori .NET.

Mi sono trovato con questo problema apparentemente banale:

Dal database mi venivano restituiti valori di tipo Money, che venivano memorizzati come Decimal in una classe. La conversione Money-Decimal si porta dietro 4 cifre decimali, a prescindere dal valore. Vorrei quindi troncare queste cifre quando non serve. Ad esempio, vorrei convertire 12000,0000 in 12000.

Problema semplice, ma come? Considerate che non avevo un solo decimal, ma circa 200 valori memorizzati così. La soluzione immediata è utilizzare (12000.0000m).ToString("F") o Decimal.Truncate(12000.0000m) per troncare le cifre decimali, ma questo dovrei scriverlo 200 volte, e odio fare copia e incolla “sintomo di cattiva programmazione”.

Allora quello che mi serviva era:

Creare un metodo di utilità che mi consentisse di modificare tutte le cifre decimali in tutto il grafo degli oggetti che conteneva il mio oggetto di partenza.

Vorrei dunque creare un metodo come questo:

Bilancio bilancio = ImportBilancio();
PropertyModifier.ApplyToAllOfType<decimal>(bilancio, delegate(decimal number)
{
    decimal numberTruncated = Decimal.Truncate(number);
    Debug.Write(String.Format(" [Troncato: {0} -> {1}]", number.ToString(), numberTruncated.ToString()));
    return numberTruncated;
});

Riporto quindi la classe che consente questa utilissima funzione, per chiunque ne avesse bisogno:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using System.Collections;

namespace PropertyModifier
{
    public class PropertyModifier
    {
        public delegate T MethodModifier<T>(T t);

        private static BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;

        public static void ApplyToAllOfType<T1>(object obj, MethodModifier<T1> modifier)
        {
            ApplyToAllOfType<T1>(obj, modifier, 0, true);
        }

        private static void ApplyToAllOfType<T1>(object obj, MethodModifier<T1> modifier, int indent, bool printCurrent)
        {
            if (obj == null)
                return;

            Type objType = obj.GetType();

            if (printCurrent)
            {
                DebugWriteNode(objType.Name, indent);
                Debug.WriteLine(""); // vai a capo
            }

            /* Scandisci proprieta' */
            foreach (PropertyInfo prop in objType.GetProperties(flags))
            {
                /* Se e' leggibile e non e' indexed, ottieni valore */
                if (prop.CanRead && prop.CanWrite && prop.GetGetMethod().GetParameters().Length == 0)
                {
                    object propValue = prop.GetValue(obj, null);
                    if (propValue != null && !propValue.Equals(obj)) // previene cicli
                    {
                        DebugWriteNode(String.Format("p:{0}={1}",prop.Name, propValue), indent);
                        if (propValue is T1)
                        {
                            object modifiedValue = modifier((T1)propValue);
                            prop.SetValue(obj, modifiedValue, null);
                        }
                        Debug.WriteLine(""); // vai a capo
                        ApplyToAllOfType<T1>(propValue, modifier, indent + 1, false);
                    }
                }
            }

            /* Scandisci campi */
            foreach (FieldInfo field in objType.GetFields(flags))
            {
                if (!field.IsInitOnly && !field.IsLiteral)
                {
                    object fieldValue = field.GetValue(obj);
                    if (fieldValue != null && !fieldValue.Equals(obj)) // previene cicli
                    {
                        DebugWriteNode(String.Format("f:{0}={1}", field.Name, fieldValue), indent);
                        if (fieldValue is T1)
                        {
                            object modifiedValue = modifier((T1)fieldValue);
                            field.SetValue(obj, modifiedValue);
                        }
                        Debug.WriteLine(""); // vai a capo
                        ApplyToAllOfType<T1>(fieldValue, modifier, indent + 1, false);
                    }
                }
            }

            /* Se ho un elemento enumerabile, prendi gli elementi */
            if (obj is IEnumerable)
            {
                IEnumerable enumerableObj = (IEnumerable)obj;
                int currElement = 1;
                foreach (object childObj in enumerableObj)
                {
                    DebugWriteNode(String.Format("{0}:{1}={2}", currElement++, objType.Name, childObj), indent);
                    Debug.WriteLine(""); // vai a capo
                    ApplyToAllOfType<T1>(childObj, modifier, indent + 1, false);
                }
            }
        }

        private static void DebugWriteNode(string nameToPrint, int indent)
        {
            for (int i = 0; i < indent; i++)
            {
                Debug.Write("|   ");
            }
            Debug.Write("+ " + nameToPrint);
        }
    }
}

Posted in .net | 1 Comment »

Gestione Globale e Centralizzata dell’Errore in ASP.NET

Posted by Ricibald on 30th January 2008

Tipicamente un’applicazione con interfaccia console o window la gestione globale dell’errore è piuttosto semplice.

Nel caso di interfaccia console:

static int Main(string[] args)
{
  try
  {
    // Do application logic here
    return 0;
  }
  catch (ParseCommandLineException pce)
  {
    Console.WriteLine("Usage error");
    return 27;
  }
  catch (Exception e) {
    Console.WriteLine(e);
    return 42;
  }
}

Nel caso di interfaccia WinForm:

[STAThread]
static void Main()
{
  Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
  Application.Run(new Form1());
}

private void button1_Click(object sender, System.EventArgs e)
{
  throw new Exception("Whoops");
}

private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
  MessageBox.Show(e.Exception.Message);
}

Nel caso invece di applicazione web verrebbe naturale ragionare nello stesso modo, scrivendo qualcosa come:

public class MyPage : System.Web.UI.Page
{
    private string _errorMessage;
    public string ErrorMessage { get { return _errorMessage; } }
    protected new PageMaster Master { get { return (PageMaster)Page.Master; } }

    protected void Page_Error(object sender, EventArgs e)
    {
    	Exception objErr = Server.GetLastError();
        EventLog.WriteEntry("MyWebform.aspx",err,EventLogEntryType.Error);
        _errorMessage = objErr.Message;
        Server.ClearError();
        Server.Transfer(this.AppRelativeVirtualPath);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        /* Stampa messaggio di errore se presente */
        if (this.PreviousPage != null)
        {
            MyPage previousPage = (MyPage)this.PreviousPage;
            Master.ErrorLabel = previousPage.ErrorMessage;
        }
    }
}

Ma questo comporta il seguente problema:

Poiché la pagina deve poter essere completamente reinviata, perdo tutti i valori immessi dall’utente.

In altre parole, vorrei ottenere un PostBack con il messaggio di errore, ma il PostBack non può essere riprodotto.

Potremmo pensare diverse soluzioni:

  • Si potrebbe provare a simulare il PostBack, forzando il salvataggio dei dati immessi in sessione per poi ricaricarli, ma .NET non lo permette
  • Si potrebbe inviare una risposta HTTP personalizzata con il contenuto della pagina con associati i controlli immessi, ma non funziona
  • Potremmo utilizzare AJAX per aggiornare solo la differenza di ciò che è cambiato. In questo caso funzionerebbe, ma:
    • si obbligherebbe qualunque pulsante o qualunque metodo che potrebbe scatenare un’eccezione ad essere definito dentro un UpdatePanel, cosa sconsigliata per le prestazioni
  • Invece di ricaricare la stessa pagina che ha causato l’errore potremmo eseguire una Transfer verso una pagina di errore a cui passiamo il messaggio di errore tramite CrossPagePostback. A questo punto potremmo fornire un pulsante “Torna indietro” che esegue il “Back” nella cronologia del browser. In questo caso funzionerebbe, ma:
    • Dobbiamo “fidarci” della cache del browser
    • Dobbiamo obbligare il browser a fare uso di javascript per tornare indietro
    • In presenza di precedenti aggiornamenti AJAX il pulsante “Back” crea problemi: torna indietro solo del PostBack parziale. Potremmo utilizzare soluzioni articolate, come l’uso del server control History, ma non supportato nel framework 2.0

Dopo lunghe peripezie si può arrivare per ora ad una conclusione: bisogna abbandonare l’idea di gestire l’errore nel Page_Error. E allora come fare? Analizziamo quando possono avvenire gli errori nelle pagine ASP.NET:

  • nell’inizializzazione delle pagine
  • nelle PostBack, sincrone e asincrone

Per gestire l’errore “basterebbe” mettere un try/catch in tutte le parti di tutte le pagine. Per l’inizializzazione delle pagine si potrebbe pensare di gestire eventuali eccezioni in una classe Page customizzata che fa da padre per tutte le pagine che implementeremo. Potremmo quindi utilizzare il pattern Template come segue:

public abstract class MyPage : System.Web.UI.Page
{
    private string _errorMessage;
    public string ErrorMessage { get { return _errorMessage; } }
    protected new PageMaster Master { get { return (PageMaster)Page.Master; } }

    protected abstract void Specific_Page_Load(object sender, EventArgs e);

    protected void Page_Load(object sender, EventArgs e)
    {
        /* Stampa messaggio di errore se presente */
        if (this.PreviousPage != null)
        {
            MyPage previousPage = (MyPage)this.PreviousPage;
            Master.ErrorLabel = previousPage.ErrorMessage;
        }
        try
        {
            Specific_Page_Load(sender, e);
        }
        catch(Exception objErr)
        {
            _errorMessage = objErr.Message;
        }
    }
}

public class LoginPage : MyPage
{
    protected override void Specific_Page_Load(object sender, EventArgs e)
    {
        LoadControls(); // questo potrebbe causare un errore
    }
}

Ma esiste comunque un problema:

Il client che utilizza MyPage si deve ricordare di non implementare mai il Page_Load, ma di implementare solo ed esclusivamente il Specific_Page_Load ereditato.

Vorremmo invece che l’utente non sia costretto a seguire un ordine mentale: il sistema deve gestire il controllo in modo trasparente. Per fare questo bisogna capire se esiste un metodo perno di tutti i Load, il cui fallimento comporta un fallimento di un qualunque eventuale load specializzato. Questo metodo esiste, ed è OnLoad, che richiama tutti i Page_Load (non gli OnLoad) creati seguendo il cosiddetto “Principio Di Hollywood” . Basta quindi sovrascrivere OnLoad in questo modo:

public abstract class MyPage : System.Web.UI.Page
{
    protected new PageMaster Master { get { return (PageMaster)Page.Master; } }

    protected override void OnLoad(EventArgs e)
    {
        try
        {
            base.OnLoad(e);
        }
        catch(Exception objErr)
        {
            Master.ErrorLabel = objErr.Message;
        }
    }
}

In modo analogo si può sovrascrivere il metodo perno di tutti i PostBack, RaisePostBackEvent.

Vogliamo infine perfezionare questa gestione rendendola generica e riutilizzabile.

Metto quindi a disposizione di chiunque fosse interessato la mia soluzione per la gestione globale delle eccezioni. Chi utilizzerà questa classe è sufficiente che tutte le pagine ereditino dalla vostra pagina customizzata, che a sua volta eredita dalla mia. La vostra pagina customizzata dovrà quindi implementare il metodo HandleError e il gioco è fatto.

using System;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Drawing;
using System.Reflection;

namespace GenericException
{
    /// <summary>
    /// Inoltra tutte le richieste, ma gestisce l'eccezione e consente di visualizzarla
    /// </summary>
    public abstract class ExceptionManageablePage : System.Web.UI.Page
    {
        protected abstract void HandleError(Exception exception);

        private delegate void MethodToTryCatchOneParam<Param1>(Param1 arg1);
        private delegate void MethodToTryCatchTwoParam<Param1, Param2>(Param1 arg1, Param2 arg2);

        private void ManageErrors<Param1>(MethodToTryCatchOneParam<Param1> method, Param1 arg1)
        {
            try
            {
                method(arg1);
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void ManageErrors<Param1, Param2>(MethodToTryCatchTwoParam<Param1, Param2> method, Param1 arg1, Param2 arg2)
        {
            try
            {
                method(arg1, arg2);
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        protected override void OnAbortTransaction(EventArgs e)
        {
            ManageErrors(base.OnAbortTransaction, e);
        }

        protected override void OnCommitTransaction(EventArgs e)
        {
            ManageErrors(base.OnCommitTransaction, e);
        }

        protected override void OnDataBinding(EventArgs e)
        {
            ManageErrors(base.OnDataBinding, e);
        }

        protected override void OnError(EventArgs e)
        {
            ManageErrors(base.OnError, e);
        }

        protected override void OnInit(EventArgs e)
        {
            ManageErrors(base.OnInit, e);
        }

        protected override void OnInitComplete(EventArgs e)
        {
            ManageErrors(base.OnInitComplete, e);
        }

        protected override void OnLoad(EventArgs e)
        {
            ManageErrors(base.OnLoad, e);
        }

        protected override void OnLoadComplete(EventArgs e)
        {
            ManageErrors(base.OnLoadComplete, e);
        }

        /// <summary>
        /// Cattura eccezioni di qualunque postback, anche asincrono tramite Ajax. Ma in questo
        /// ultimo caso anche l'HandleError deve supportare aggiornamenti asincroni (Label dentro un UpdatePanel)
        /// </summary>
        protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
        {
            ManageErrors(base.RaisePostBackEvent, sourceControl, eventArgument);
        }

    }
}

Bisogna infine dire che per i postback asincroni devo avere una gestione dell’errore che stampi un messaggio asincrono. Basta quindi inserire una label di errore con un UpdatePanel, o utilizzare una ModalPopupExtender. E ovviamente ogni consiglio è più che benvenuto!

Posted in .net | 2 Comments »