Sviluppo Cross Language

.::Home::.

.::Introduzione::.

1.Panoramica

4.DataBase

.::Presentazioni PPT::.

.::Link::.

.::DownLoad::.

 

In questo esempio si vuole mettere in evidenza uno degli aspetti più interessanti della piattaforma .NET, ovvero l'estrema facilità di utilizzo di più linguaggi di programmazione nel contesto di un unico progetto.

Saranno creati due assembly: il primo è una libreria di tipo DLL che definisce una semplice classe di base scritta con le estensioni gestite (managed extension) per C++; il secondo assembly è un eseguibile che definisce tre classi derivate scritte rispettivamente in C#, Visual Basic e in Intermediate Language. Questi tipi derivano l'uno dall'altro e infine dalla classe di base in managed C++.

Per concludere l'eseguibile crea istanze di ognuno dei tipi derivati e chiama un metodo virtuale per uno.

Questo esempio è puramente didattico e fortemente semplificato, ma fornisce un'idea di come .NET Framework sia un ambiente dove molti sviluppatori possono lavorare insieme indipendentemente dal linguaggio di programmazione scelto.

VCBase.cpp

#using ‹mscorlib.dll›
using namespace System;

__gc public class VCBase
{
protected:
   VCBase(){
      Console::WriteLine(" Executing the VCBase::VCBase() constructor");
   }
	
public:
   virtual void Method() = 0;
   void MethodThatThrows(){
      throw(new OutOfMemoryException("We are out of some resource!"));
   }

};

Questo codice crea una semplice classe di base scritta in C++, gli altri moduli creeranno classi derivate da questa, ma saranno scritti in Visual Basic, C# e IL.

Le considerazioni sull'assembly mscorlib.dll sono identiche a quelle viste nell'esempio precedente (hello world!).

.NET Framework, offre una funzione di Garbage Collection (GC), che facilita lo sviluppo abilitando l'ambiente a tener traccia delle risorse, come gli oggetti, ed automaticamente rilasciarle quando non sono più necessarie.

La keyword __gc nella dichiarazione della classe VCBase marca la classe come "gestita", permettendo questo meccanismo.

Una scritta su console (" Executing the VCBase::VCBase() constructor") avvisa quando è creata una istanza della classe VCBase (constructor).

Il metodo Method non fa nulla, ma non serve perchè verrà subito scavalcato da un Method da esso derivato nella classe in Visual Basic.

Piuttosto che un throw esplicito, quello finale agisce in caso in cui il codice acceda a risorse non disponibili.

VBDerived.vb

Option Explicit On 
Option Strict On

Imports System

Public Class VBDerived 
Inherits VCBase

   Public Sub New()
      REM MyBase.New

      Console.WriteLine("  Executing the VBDerived.New() constructor")

   End Sub

   Overrides Public Sub Method
      Console.WriteLine(" Executing the VBDerived.Method() virtual method")
   End Sub

   Public Sub AnotherMethodThatThrows
      Try
         MyBase.MethodThatThrows()      
      Catch e As OutOfMemoryException
         Throw(new ApplicationException("Some application function failed!", e))
      End Try
   End Sub

End Class

Questo codice dimostra un semplice tipo scritto in Visual Basic e derivato da VCBase [Inherits VCBase]...
[Anche in questo caso c'e' un avviso di istanza su schermo e un "Method" che scrive una stringa su console quando eseguito. Esso eredita il precedente Method di VCBase e lo sostituisce completamente grazie alla parola chiave Overrides (override in C#)]

ILDerived.il

.module extern VBDerived.netmodule

.class public auto ansi ILDerived
       extends [.module VBDerived.netmodule]VBDerived
{
  .method public specialname rtspecialname 
          instance void .ctor() il managed
  {
    .maxstack  1
    .locals init (class System.Object[] V_0)
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [.module VBDerived.netmodule]VBDerived::.ctor()
    IL_0006:  ldstr      "   Executing the ILDerived::ctor() constructor"
    IL_000b:  call       void [mscorlib]System.Console::WriteLine(class System.String)
    IL_0010:  ret
  } 

  .method public virtual instance void Method() il managed
  {
    .maxstack  1
    .locals init (class System.Object[] V_0)
    IL_0000:  ldstr      " Executing the ILDerived::Method() virtual method"
    IL_0005:  call       void [mscorlib]System.Console::WriteLine(class System.String)
    IL_000a:  ret
  }
}

... la stessa cosa derivando in Intermediate Language la classe VBDerived definita qui sopra...

CSDerived.cs

using System;

public class CSDerived:ILDerived{
   public CSDerived(){
      Console.WriteLine("    Executing the CSDerived.CSDerived() constructor");
   }      

   override public void Method(){
      Console.WriteLine(" Executing the CSDerived.Method() virtual method");
   }
}

... ed infine l'analogo in C#, derivato dalla classe ILDerived [class CSDerived:ILDerived].

CrossLang.cs

using System;
using System.Security;

class App{
   public static void Main(){
      try{
         CrossObj();
      }catch(VerificationException){
         Console.WriteLine("A VerificationException has been thrown "+
            "(and caught). Run this\nsample from your local "+
            "hard-drive to avoid this exception.");
      }
   }
   
   static void CrossObj(){
      // Crea un array di oggetti per immagazzinare quelli definiti 
      //negli altri linguaggi
      VCBase[] objects = new VCBase[3];

      // Carica nella posizione 0 dell'array l'oggetto 
      //creato usando IL
      Console.WriteLine("\nCreating object:  ILDerived");
      objects[0] = new ILDerived();

      // Carica nella posizione 1 dell'array l'oggetto 
      //creato usando C#
      Console.WriteLine("\nCreating object:  CSDerived");
      objects[1] = new CSDerived();

      // Carica nella posizione 2 dell'array l'oggetto 
      //creato usando VB
      Console.WriteLine("\nCreating object:  VBDerived");
      objects[2] = new VBDerived();

      // Chiama il metodo virtuale di ogni oggetto
      Console.WriteLine("\nCalling Methods");
      foreach(VCBase obj in objects){
         obj.Method();
      }

      // Test sull'eccezione
      try{
      (objects[2] as VBDerived).AnotherMethodThatThrows();
      }catch(ApplicationException){
         // Risponde al fallimento
      }
   }
}

CrossLang.cs darà forma all'assembly eseguibile.

Per prima cosa viene creato un array nel quale saranno caricati gli oggetti creati sulla base di quelli definiti nei vari sorgenti presentati.

In posizione 0 viene caricato l'oggetto creato a partire da ILDerived. Essendo l'oggetto derivato da VBDerived a sua volta discendente da VCBase i relativi "Constructor" saranno richiamati dando luogo all'output:

Creating object:  ILDerived
 Executing the VCBase::VCBase() constructor
  Executing the VBDerived.New() constructor
   Executing the ILDerived::ctor() constructor

Analogamente, in posizione 1 dell'array è caricato l'oggetto creato da CSDerived, derivato da ILDerived derivato da VBDerived a sua volta ancora discendente da VCBase.

L'output su console in questo caso risulta:

Creating object:  CSDerived
 Executing the VCBase::VCBase() constructor
  Executing the VBDerived.New() constructor
   Executing the ILDerived::ctor() constructor
    Executing the CSDerived.CSDerived() constructor

Infine da VBDerived è creato l'oggetto posto nell'ultima locazione dell'array, ed essendo derivato direttamente da VCBase genera:

Creating object:  VBDerived
 Executing the VCBase::VCBase() constructor
  Executing the VBDerived.New() constructor

A questo punto mediante foreach, che permette di scorrere un array (trattato separatamente in questo tutorial) il metodo virtuale presente in ogni oggetto viene eseguito:

Calling Methods
 Executing the ILDerived::Method() virtual method
 Executing the CSDerived.Method() virtual method
 Executing the VBDerived.Method() virtual method 

Fonti:

Documentazione .NET Framework SDK

.::^top^::.

(2002) A cura di Carlo Becchi