Reflection e assembly

A volte potrebbe tornare utile utilizzare librerie .NET (assembly) sviluppate da terzi o da noi stessi con la versione precedente del Framework .NET oppure da differenti linguaggi tra C# & VB o viceversa. Il sostanza la Reflection rende portabile gli assembly in altra applicazione .NET senza bisogno di aggiungere la libreria tra i riferimenti nel progetto di Visual Studio, ma è sufficiente aggiungere fisicamente l'assembly nella directory bin dell'applicazione oppure indicare il path della directory.

Dim assemblyVer1x As [Assembly] = [Assembly].Load("AssemblyVer1x") 

oppure

Dim assemblyVer1x As [Assembly] = [Assembly].LoadFrom("C:\Temp\AssemblyVer1x.dll") 

Per accedere alla classe Assembly bisogna importare nella nostra classe il namespace:

Imports System.Reflection 

In seguito si sceglie il tipo contenuto nell'assembly da cui successivamente ottenerne l'istanza ed invocare metodi o interagire con proprietà.

Dim tp As Type = assemblyVer1x.GetType("AssemblyVer1x.Persona", True

E possibile passare un array (argsCostructor) di argomenti che contengono parametri del costruttore come nel nostro caso della classe AssemblyVers1x.Persona

Dim istance As Object = assemblyVer1x.CreateInstance(tp.FullName, True, _ BindingFlags.CreateInstance, Nothing, argsCostructor, NothingNothing)

Va preso in considerazione che prima bisogna ottenere tutte le informazioni dei nomi dei tipi e membri della classe AssemblyVers1x.Persona

Dall' oggetto Type è possibile recuperare le istanze PropertyInfo  o  MethodInfo in modo da interagire con proprietà e metodi della classe AssemblyVers1x.Persona

Dim properties As PropertyInfo() = New PropertyInfo(1) {}
properties(0) = tp.GetProperty("Nome")
properties(1) = tp.GetProperty("Cognome")
Dim nome As String CType(properties(0).GetValue(istance, Nothing), String)
Dim cognome As String CType(properties(1).GetValue(istance, Nothing), String)

A questo punto si può continuare ad esplorare e testare la libreria in modo da verificarne l'affidabilità.
Qui sotto riporto un esempio completo di una classe in VB8 che fa uso di una libreria scritta in C# 1.0

Option Explicit On
Option Strict On

Imports 
System.Reflection

Class TestReflection

    
Private Enum MethodFlags
        IncassaStipendio
        ControllaCassa
        GetPortafoglio
        FaiLaSpesa
        VersaMutuoOAffitto
        VersaTassa
    
End Enum

    Shared Sub 
Main(ByVal args As String())
        
Try
            Dim 
argsCostructor As Object() = New Object(1) {}
            Console.
Write("Inserisci il tuo nome: ")
            argsCostructor(0) = Console.ReadLine()

            Console.WriteLine()
            Console.
Write("Inserisci il tuo cognome: ")
            argsCostructor(1) = Console.ReadLine()

            
Dim assemblyVer1x As [Assembly] = [Assembly].LoadFrom("C:\Temp\AssemblyVer1x.dll")
            
Dim tp As Type = assemblyVer1x.GetType("AssemblyVer1x.Persona", True)

            
Dim istance As Object = assemblyVer1x.CreateInstance(tp.FullName, True, _
                BindingFlags.CreateInstance, 
Nothing, argsCostructor, NothingNothing)

            
Dim properties As PropertyInfo() = New PropertyInfo(1) {}
            properties(0) = tp.GetProperty("Nome")
            properties(1) = tp.GetProperty("Cognome")

            
Dim nome As String CType(properties(0).GetValue(istance, Nothing), String)
            
Dim cognome As String CType(properties(1).GetValue(istance, Nothing), String)

            Console.WriteLine()
            Console.WriteLine("Benvenuto {0} {1}", nome, cognome)
            Console.WriteLine()
            Console.
Write("Quanti euri hai percepito di stipendio in questo mese?: ")

            
Dim stipendio As Decimal = Convert.ToDecimal(Console.ReadLine())
            
Dim methods As MethodInfo() = TestReflection.LoadMethods(tp)
            
Dim status As Object() = New Object(0) {}

            methods(MethodFlags.IncassaStipendio).Invoke(istance, 
New Object(0) {stipendio})
            
Dim tesoretto As Decimal = Convert.ToDecimal(methods(MethodFlags.GetPortafoglio).Invoke(istance, status))

            Console.WriteLine()
            Console.WriteLine("Complimenti, {0} euro {1}, visto i prezzi e tasse aumentano sempre si potrebbe cercare un aumentino di stipendio.", tesoretto, status(0))

            Console.WriteLine()
            Console.
Write("Quanti euri intendi spendere di stipendio in questo mese?: ")
            
Dim spesa As Decimal = Convert.ToDecimal(Console.ReadLine())
            TestReflection.Paga(methods, istance, spesa, MethodFlags.FaiLaSpesa)

            Console.WriteLine()
            Console.
Write("Quanti euri devi pagare di affitto o mutuo in questo mese?: ")
            spesa = Convert.ToDecimal(Console.ReadLine())
            TestReflection.Paga(methods, istance, spesa, MethodFlags.VersaMutuoOAffitto)

            Console.WriteLine()
            Console.
Write("Quanti euri devi pagare di tasse in questo mese?: ")
            spesa = Convert.ToDecimal(Console.ReadLine())
            TestReflection.Paga(methods, istance, spesa, MethodFlags.VersaTassa)

            tesoretto = Convert.ToDecimal(methods(MethodFlags.GetPortafoglio).Invoke(istance, status))

            Console.WriteLine()
            Console.WriteLine("E gia {0} {1}! Con i rimanenti {2} euri al mese immagino " & _
                "che il tuo stato d'animo diventi così {3}", nome, cognome, tesoretto, status(0))
        
Catch ex As FormatException
            Console.WriteLine()
            Console.WriteLine("Input non corretto. Riprova da capo.")
        
Catch ex As Exception
            
Console.WriteLine()
            Console.WriteLine(ex.Message)
        
Finally
            
Console.WriteLine()
            Console.
Write("Premi un tasto per terminare")
            Console.Read()
        
End Try
    End Sub

    Shared Sub 
Paga(ByVal methods As MethodInfo(), ByVal istance As ObjectByVal spesa As DecimalByVal methodIndex As Integer)
        
Try
            
methods(MethodFlags.ControllaCassa).Invoke(istance, New Object(0) {spesa})
            methods(methodIndex).Invoke(istance, 
New Object(0) {spesa})
        
Catch ex As TargetInvocationException
            Console.WriteLine(ex.InnerException.Message)
            Console.WriteLine()
            Console.
Write("Sicuro di continuare? S/N: ")
            
Dim risposta As Char = Convert.ToChar(Console.ReadLine())
            
If Char.ToUpper(risposta) = "S"c Then methods(methodIndex).Invoke(istance, New Object(0) {spesa})
        
End Try
    End Sub

    Shared Function 
LoadMethods(ByVal tp As TypeAs MethodInfo()
        
Dim flags As MethodFlags() = DirectCast([Enum].GetValues(GetType(MethodFlags)), MethodFlags())
        
Dim methods As MethodInfo() = New MethodInfo(flags.Length - 1) {}

        
For Each As MethodFlags In flags
            methods(m) = tp.GetMethod(
String.Format("{0:G}", m))
        
Next

        Return 
methods
    
End Function

End Class

  

using System;

namespace AssemblyVer1x
{
    
public class Persona
    {
        
string nome, cognome; 
        Decimal stipendio = 0;
        
string[] faccine = {":-)",":-/"};
        
private enum Faccia{Allegra = 0,Triste = 1}

        
public Persona(string nome, string cognome)
        {
            
this.nome = nome;
            
this.cognome = cognome;
        }

        
public string Nome
        {
            
get return this.nome; }
            
set this.nome = value;}
        }

        
public string Cognome
        {
            
get return this.cognome; }
            
set this.cognome = value;}
        }

        
public void VersaTassa(decimal tassa)
        {
            
this.stipendio -= tassa;
        }

        
public void VersaMutuoOAffitto(decimal rata)
        {
            
this.stipendio -= rata;
        }

        
public void FaiLaSpesa(decimal spesa)
        {
            
this.stipendio -= spesa;
        }

        
public void IncassaStipendio(decimal stipendio)
        {    
            
this.stipendio += stipendio;
        }

        
public Decimal GetPortafoglio(out string stato)
        {

            
if (stipendio <=0)
                stato = faccine[(
int)Faccia.Triste];
            
else
                
stato = faccine[(int)Faccia.Allegra];

            
return stipendio;
        }

        
public void ControllaCassa(Decimal importo)
        {
            Decimal differenza = 
this.stipendio - importo;

            
if (differenza<=0)
                
throw new SenzaUnCentesimoException();
        }
    }

    
public class SenzaUnCentesimoException : ApplicationException 
    {
        
public SenzaUnCentesimoException():base("Attenzione!" + 
            "Rischi davvero di non arrivare a fine mese!"){}
    }
}

Skins

Devo ammettere che fa piacere avere a disposizione nuovi skins per i blogs di Ugidotnet.

L'unica cosa che mi dispiace è che Firefox interpreta discretamente il layout del blog, mentre Internet explorer lascia desiderare in alcuni skins.

ASP.NET contro Excel

Ultimamente ho affrontato il capitolo “interoperabilità tra ASP.NET 2.0 ed Excel”, che all’apparenza sembrava semplice da gestire come nelle applicazioni Windows Forms. Di fatti non lo è, in quanto si rischia di lasciare appesi i processi di EXCEL.EXE sul server web IIS 5.0/6.0.

 

Dopo aver usato i componenti PIA e la funzione Marshal.ReleaseComObject mi aspettavo di chiudere i processi COM di Excel. Ma niente.

 

Ne sono venuto fuori sfruttando il Late Binding, senza utilizzare i PIA, affidandomi invece alla vecchia istruzione CreateObject che si utilizzava nelle pagine ASP 3.0, dichiarando tutti gli oggetti di Excel in Object anziche i tipi del namespace Microsoft.Office.Interop.Excel

 

In più bisogna ricordare di rilasciare dalla memoria gli oggetti in sequenza, dall’ultimo al primo chiamato come suggerisce il bravo Antony

Più di zero è gia qualcosa.

Da tempo che leggo blogs, forse sono un paio d'anni or sono. Direi che c'è chi si diverte a bloggare, sia per una questione di crescita professionale sia per un reciproco scambio di conoscenze, impressioni. Molte volte, la stessa cosa accade tra colleghi di lavoro in carne ed ossa e non virtualmente, ma il principio è pressoché simile. C’è sempre da imparare anche quando si è convinti di sapere quanto basta per portare a conclusione un software nel minor tempo e al minor costo possibile. La sfida è sempre la solita, comprendere e scegliere le soluzioni migliori, probabilmente le ultime tecnologie sono sempre quelle più idonee. Ma la massa di argomenti non è cosa da poco. C’è chi si perde d’animo e molla tutto, c’è chi si prende i suoi tempi, c’è chi pur faticando molto arriva dove si era prefissato d’arrivare. Mattone dopo mattone, la costruzione prende forma, ma non è mai finita. Perché? Perché invecchia e bisogna ristrutturarla. Malgrado gli antiossidanti il processo d’invecchiamento vale per tutti. Se c’è da sudare, meglio farlo finchè si è ancora giovani e/o sani. E con questo mi auguro di continuare a bloggare (non è vietato, credo) malgrado gli scettici e i critici saranno sempre a portata di mano. Al prossimo post. Grazie ;-)
«May»
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910