.NET MAUI 10: Guida Completa a Prestazioni, NativeAOT e Diagnostica Avanzata

Tutto su .NET MAUI 10: compilazione XAML 100x più veloce, app 2.5x più piccole con NativeAOT, sistema di osservabilità con OpenTelemetry e Aspire, CoreCLR sperimentale su Android e guida pratica alla migrazione.

Introduzione a .NET MAUI 10: Finalmente si Parla di Qualità

Se seguite l'evoluzione di .NET MAUI da un po', sapete che le versioni precedenti hanno avuto il loro bel da fare nel mettere in piedi le fondamenta. Con .NET MAUI 10, però, le cose cambiano marcia. Questa release si concentra su tre pilastri che gli sviluppatori chiedevano a gran voce: qualità, prestazioni e strumenti di diagnostica. E, onestamente, era ora.

Il team di sviluppo ha finalmente ascoltato il feedback della comunità in modo concreto. Tempi di compilazione estenuanti? Affrontati. App troppo pesanti? Ridotte. Avvio lento? Velocizzato. E non si tratta di promesse vaghe — i numeri parlano chiaro, come vedremo tra poco.

Tra le novità più interessanti c'è la generazione del codice XAML a tempo di compilazione (che riduce i tempi di build in Debug in modo impressionante), il supporto NativeAOT su più piattaforme con app fino a 2.5 volte più piccole, e un sistema di osservabilità completamente nuovo basato su ActivitySource e Meter. Insomma, roba concreta.

Vediamo nel dettaglio cosa porta questa versione.

XAML Source Generation: Compilazione Finalmente Veloce

Ok, partiamo con quella che è probabilmente la novità più impattante per la vita quotidiana di chi sviluppa con MAUI: la XAML Source Generation. Se avete mai aspettato minuti interminabili per una build in Debug, questa funzionalità vi cambierà la giornata.

Come Funziona

Fino ad oggi, i file XAML venivano processati a runtime usando la reflection per istanziare controlli, impostare proprietà e gestire binding. Funzionava, certo, ma con un overhead non trascurabile — specialmente in Debug, dove ogni ricostruzione richiedeva la ri-interpretazione completa di tutti i file XAML.

Con .NET MAUI 10, il compilatore genera automaticamente codice C# equivalente per ogni file XAML durante la compilazione. Niente più reflection, niente più parsing XML a runtime.

I risultati? Giudicate voi:

  • 100 volte più veloce in modalità Debug — sì, avete letto bene, cento volte
  • 25% più veloce in Release — anche le build di produzione ne beneficiano
  • Meno reflection — prestazioni runtime migliori in generale
  • Migliore supporto per il trimming — il codice generato è più facile da analizzare per gli strumenti di ottimizzazione

Come Abilitarla

Abilitare la XAML Source Generation è semplicissimo. Basta aggiungere una proprietà al file .csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net10.0-android;net10.0-ios;net10.0-maccatalyst</TargetFrameworks>
    <OutputType>Exe</OutputType>
    <RootNamespace>MiaApp</RootNamespace>
    <UseMaui>true</UseMaui>

    <!-- Abilita la XAML Source Generation -->
    <MauiXamlInflator>SourceGenerator</MauiXamlInflator>
  </PropertyGroup>
</Project>

Una riga. Tutto qui. Una volta abilitata, ogni file XAML genera un file .g.cs corrispondente nella cartella obj, compilato automaticamente col resto del codice.

Cosa Viene Generato in Pratica

Per capire meglio, prendiamo un XAML semplice:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MiaApp.MainPage">
    <VerticalStackLayout Padding="30,0" Spacing="25">
        <Label Text="Benvenuto in .NET MAUI 10!"
               FontSize="32"
               HorizontalOptions="Center" />
        <Button x:Name="ContaButton"
                Text="Clicca qui"
                Clicked="OnContaButtonClicked" />
    </VerticalStackLayout>
</ContentPage>

Il source generator trasforma tutto questo in codice C# pulito:

partial class MainPage
{
    private Button ContaButton;

    private void InitializeComponent()
    {
        var verticalStackLayout = new VerticalStackLayout
        {
            Padding = new Thickness(30, 0),
            Spacing = 25
        };

        var label = new Label
        {
            Text = "Benvenuto in .NET MAUI 10!",
            FontSize = 32,
            HorizontalOptions = LayoutOptions.Center
        };

        ContaButton = new Button
        {
            Text = "Clicca qui"
        };
        ContaButton.Clicked += OnContaButtonClicked;

        verticalStackLayout.Children.Add(label);
        verticalStackLayout.Children.Add(ContaButton);

        Content = verticalStackLayout;
    }
}

Compatibilità e Qualche Limite

La buona notizia è che la XAML Source Generation funziona con la maggior parte delle app MAUI esistenti senza modifiche. Ci sono però alcune cose da tenere a mente:

  • Binding molto complessi o espressioni XAML particolarmente dinamiche potrebbero richiedere qualche aggiustamento
  • Le custom markup extension devono essere compatibili con la generazione di codice
  • Il debugging ora mostra il codice C# generato invece del markup originale (che in realtà può essere un vantaggio)

Nel complesso, i benefici superano di gran lunga le piccole attenzioni necessarie. Abilitatela — non ve ne pentirete.

Namespace XML Globali: Basta con le Dichiarazioni Ripetute

.NET MAUI 10 introduce un sistema migliorato per gestire i namespace XML nei file XAML. Se siete stanchi di copiare e incollare le stesse dichiarazioni xmlns in ogni pagina, questa novità fa per voi.

Il Problema (Che Conosciamo Tutti)

Nelle versioni precedenti, ogni volta che serviva un controllo personalizzato o un converter, toccava dichiarare il namespace completo in ogni singolo file:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controls="clr-namespace:MiaApp.Controls"
             xmlns:viewmodels="clr-namespace:MiaApp.ViewModels"
             xmlns:converters="clr-namespace:MiaApp.Converters">
    <!-- Contenuto della pagina -->
</ContentPage>

Verboso, ripetitivo e un incubo da mantenere quando si riorganizzano i namespace.

La Soluzione: GlobalXmlns.cs

Ora si possono definire namespace XML globali a livello di assembly, centralizzati in un file dedicato:

using Microsoft.Maui.Controls.Xaml;

[assembly: XmlnsDefinition("http://miaapp.com/schemas", "MiaApp.Controls")]
[assembly: XmlnsDefinition("http://miaapp.com/schemas", "MiaApp.ViewModels")]
[assembly: XmlnsDefinition("http://miaapp.com/schemas", "MiaApp.Converters")]
[assembly: XmlnsDefinition("http://miaapp.com/schemas", "MiaApp.Behaviors")]

[assembly: XmlnsPrefix("http://miaapp.com/schemas", "app")]

E nei file XAML basta un singolo prefisso per accedere a tutto:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:app="http://miaapp.com/schemas">
    <VerticalStackLayout>
        <app:CustomHeaderControl />
        <Label Text="{Binding Nome, Converter={app:UpperCaseConverter}}" />
        <app:RatingControl Rating="{Binding Valutazione}" />
    </VerticalStackLayout>
</ContentPage>

Perfetto per Librerie Riutilizzabili

L'attributo XmlnsDefinition diventa particolarmente potente quando si creano librerie di controlli. Si possono raggruppare componenti da namespace diversi sotto un unico namespace XML:

[assembly: XmlnsDefinition("http://controlliavanzati.com/maui", "ControlliAvanzati.Charts")]
[assembly: XmlnsDefinition("http://controlliavanzati.com/maui", "ControlliAvanzati.Gauges")]
[assembly: XmlnsDefinition("http://controlliavanzati.com/maui", "ControlliAvanzati.DataGrid")]
[assembly: XmlnsDefinition("http://controlliavanzati.com/maui", "ControlliAvanzati.Input")]

[assembly: XmlnsPrefix("http://controlliavanzati.com/maui", "ctrl")]

Chi usa la libreria importa tutto con una sola dichiarazione:

<ContentPage xmlns:ctrl="http://controlliavanzati.com/maui">
    <Grid>
        <ctrl:PieChart Data="{Binding DatiVendite}" />
        <ctrl:DataGrid ItemsSource="{Binding Clienti}" />
    </Grid>
</ContentPage>

I Vantaggi Concreti

In sintesi, i namespace globali portano:

  • Meno codice ripetuto in ogni file XAML
  • Manutenzione semplificata — cambi un namespace in un punto, non in quaranta file
  • IntelliSense migliore con namespace ben definiti
  • Compatibilità piena con la XAML Source Generation

Miglioramenti ai Controlli: Le Piccole Cose che Fanno la Differenza

.NET MAUI 10 porta diversi miglioramenti ai controlli esistenti. Non sono rivoluzioni, ma sono quelle migliorie di qualità della vita che gli sviluppatori apprezzano davvero.

ShadowTypeConverter: Ombre in Una Riga

Definire un'ombra prima richiedeva un blocco XAML piuttosto verboso:

<Frame>
    <Frame.Shadow>
        <Shadow Brush="Black"
                Offset="5,5"
                Radius="10"
                Opacity="0.5" />
    </Frame.Shadow>
</Frame>

Adesso si fa così:

<Frame Shadow="5 5 10 Black 0.5">
    <!-- Contenuto del frame -->
</Frame>

<Border Shadow="0 4 8 #40000000">
    <Label Text="Testo con ombra" />
</Border>

Una riga. Molto meglio.

OffColor per Switch

Finalmente il controllo Switch ha una proprietà OffColor per personalizzare il colore in posizione Off. Sembra banale, ma quanti di voi hanno dovuto creare custom renderer solo per questo?

<Switch OnColor="Green"
        OffColor="Red"
        ThumbColor="White"
        IsToggled="{Binding NotificheAttive}" />

<Style TargetType="Switch">
    <Setter Property="OnColor" Value="{StaticResource Primary}" />
    <Setter Property="OffColor" Value="{StaticResource Gray300}" />
    <Setter Property="ThumbColor" Value="White" />
</Style>

HybridWebView.InvokeJavaScriptAsync

HybridWebView guadagna il metodo InvokeJavaScriptAsync, che permette di eseguire codice JavaScript dal lato .NET e ricevere valori di ritorno. Per chi lavora con scenari ibridi, è una manna:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private async void OnEseguiJavaScriptClicked(object sender, EventArgs e)
    {
        var risultato = await MyWebView.InvokeJavaScriptAsync(
            "document.getElementById('username').value"
        );

        UsernameLabel.Text = $"Username: {risultato}";
    }

    private async void OnCalcolaClicked(object sender, EventArgs e)
    {
        var somma = await MyWebView.InvokeJavaScriptAsync(
            "calcolaSomma(10, 20)"
        );

        await DisplayAlert("Risultato", $"La somma è: {somma}", "OK");
    }
}

Particolarmente utile quando l'interfaccia è in HTML/CSS/JavaScript ma la logica di business resta in C#.

MauiAppCompatEditText su Android

Su Android, il nuovo MauiAppCompatEditText sostituisce AppCompatEditText per Editor e Entry. Il controllo nativo migliorato offre supporto per l'evento SelectionChanged e una migliore compatibilità con Material Design:

#if ANDROID
using Microsoft.Maui.Platform;

public class CustomEntryHandler : EntryHandler
{
    protected override MauiAppCompatEditText CreatePlatformView()
    {
        var editText = base.CreatePlatformView();

        editText.SetBackgroundColor(Android.Graphics.Color.Transparent);
        editText.SetPadding(20, 20, 20, 20);

        return editText;
    }
}
#endif

Risolve problemi che affliggevano gli sviluppatori da tempo: comportamento inconsistente della tastiera, selezione del testo problematica e rendering scorretto di hint e placeholder.

Diagnostica e Osservabilità: Sapere Cosa Fa la Tua App

Questa è, a mio parere, una delle novità più sottovalutate di .NET MAUI 10. Il framework introduce un sistema di telemetria basato su ActivitySource e Meter che vi permette di capire davvero cosa succede sotto il cofano delle vostre app.

ActivitySource "Microsoft.Maui"

.NET MAUI 10 espone un ActivitySource chiamato "Microsoft.Maui" che traccia le operazioni chiave del framework. Si integra perfettamente con OpenTelemetry:

using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Trace;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });

        builder.Services.AddOpenTelemetry()
            .WithTracing(tracing =>
            {
                tracing
                    .AddSource("Microsoft.Maui")
                    .AddSource("MiaApp")
                    .SetResourceBuilder(
                        ResourceBuilder.CreateDefault()
                            .AddService("MiaApp"))
                    .AddOtlpExporter();
            });

        return builder.Build();
    }
}

Metriche di Layout con Meter

Il sistema di metriche fornisce dati quantitativi sulle prestazioni del layout. Ecco come configurarlo:

using System.Diagnostics.Metrics;
using OpenTelemetry.Metrics;

builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics =>
    {
        metrics
            .AddMeter("Microsoft.Maui")
            .SetResourceBuilder(
                ResourceBuilder.CreateDefault()
                    .AddService("MiaApp"))
            .AddOtlpExporter();
    });

Le metriche esposte includono:

  • maui.layout.measure.duration — tempi di misurazione del layout
  • maui.layout.arrange.duration — tempi di arrangiamento
  • maui.view.measure.count — contatore delle operazioni di misurazione
  • maui.view.arrange.count — contatore delle operazioni di arrangiamento

Strumentazione a Zero Allocazioni

Un dettaglio tecnico che mi ha colpito: la strumentazione è implementata con struct, quindi non introduce allocazioni di memoria aggiuntive. In pratica, misurare non altera ciò che stai misurando.

internal readonly struct LayoutMeasurement : IDisposable
{
    private readonly long _startTimestamp;
    private readonly IView _view;

    public LayoutMeasurement(IView view)
    {
        _view = view;
        _startTimestamp = Stopwatch.GetTimestamp();
    }

    public void Dispose()
    {
        var duration = Stopwatch.GetElapsedTime(_startTimestamp);
        LayoutMetrics.RecordMeasure(_view.GetType().Name, duration);
    }
}

// Utilizzo interno nel framework
public Size Measure(double widthConstraint, double heightConstraint)
{
    using var measurement = new LayoutMeasurement(this);
    return PerformMeasure(widthConstraint, heightConstraint);
}

La strumentazione si può disabilitare a runtime tramite System.Diagnostics.Metrics.Meter.IsSupported, eliminando l'overhead in produzione quando non serve.

Creare un Listener Personalizzato

Volete monitorare le prestazioni del layout in tempo reale? Potete creare un listener personalizzato:

public class LayoutPerformanceListener : IDisposable
{
    private readonly MeterListener _meterListener;

    public LayoutPerformanceListener()
    {
        _meterListener = new MeterListener();
        _meterListener.InstrumentPublished = (instrument, listener) =>
        {
            if (instrument.Meter.Name == "Microsoft.Maui")
            {
                listener.EnableMeasurementEvents(instrument);
            }
        };

        _meterListener.SetMeasurementEventCallback<double>(OnMeasurement);
        _meterListener.Start();
    }

    private void OnMeasurement(
        Instrument instrument,
        double measurement,
        ReadOnlySpan<KeyValuePair<string, object>> tags,
        object state)
    {
        var viewType = tags.FirstOrDefault(t => t.Key == "view.type").Value;

        if (measurement > 16.67) // Oltre un frame a 60fps
        {
            Debug.WriteLine(
                $"ATTENZIONE: Layout lento - {viewType}: {measurement:F2}ms");
        }
    }

    public void Dispose() => _meterListener?.Dispose();
}

Integrazione con .NET Aspire: Osservabilità Enterprise

.NET MAUI 10 si integra in profondità con .NET Aspire, portando strumenti di osservabilità di livello enterprise anche alle app mobile e desktop. Se state già usando Aspire per i vostri backend, questa integrazione è un game changer.

Template Service Defaults per MAUI

Il nuovo template "MAUI Service Defaults" fornisce una configurazione pronta all'uso per OpenTelemetry, logging e service discovery:

dotnet new maui-aspire-servicedefaults -n MiaApp.MauiServiceDefaults

Nel MauiProgram.cs basta una singola chiamata per abilitare tutto:

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });

        // Una riga per tutta la configurazione Aspire
        builder.Services.AddServiceDefaults();

        return builder.Build();
    }
}

Dev Tunnels per iOS e Android

Una delle sfide classiche nello sviluppo mobile è connettere dispositivi fisici o emulatori ai servizi backend sulla macchina di sviluppo. .NET Aspire risolve il problema con i Dev Tunnels: endpoint HTTPS accessibili pubblicamente. Il metodo WithOtlpDevTunnel() crea un tunnel specifico per il traffico OpenTelemetry, permettendo ai dati di telemetria dalle app iOS e Android di raggiungere la dashboard Aspire.

Niente più configurazione manuale di port forwarding o proxy. L'app MAUI scopre e si connette automaticamente ai servizi locali.

La Dashboard Aspire per App Mobile

Con Aspire, la dashboard fornisce una vista in tempo reale che include:

  • Trace distribuite di tutte le operazioni MAUI e chiamate API
  • Metriche di layout e rendering aggiornate in tempo reale
  • Log strutturati con correlazione automatica
  • Mappa visiva delle dipendenze tra servizi
  • Health checks e stato dell'applicazione

Per abilitare la telemetria dettagliata dal SDK MAUI, basta decommentare le righe nel file Extensions.cs del progetto Service Defaults che aggiungono "Microsoft.Maui" come sorgente. Attenzione però: può generare parecchi dati di telemetria.

NativeAOT e Trimming: App Più Piccole e Veloci

Parliamo di una delle novità più concrete di .NET MAUI 10: il supporto espanso per NativeAOT e i miglioramenti drastici al trimming. Se le dimensioni delle vostre app vi preoccupano (e dovrebbero), questa sezione è per voi.

I Numeri che Contano

Andiamo dritti al punto:

  • App 2.5 volte più piccole con NativeAOT
  • Avvio 2 volte più veloce rispetto alla compilazione JIT
  • Minor consumo di memoria senza il JIT compiler in esecuzione

Test reali con .NET 10 RC2 hanno mostrato miglioramenti nell'avvio da 1.27-1.41 secondi (MonoAOT) a 271-331 millisecondi su un Galaxy Note 10+ con inizializzazione pesante. Non male come miglioramento.

Dove Funziona

NativeAOT in .NET MAUI 10 è supportato su:

  • iOS — supporto completo
  • macOS Catalyst — supporto completo con ottimizzazioni specifiche per Mac
  • Windows — supporto per app desktop con WinUI
  • Android — non ancora supportato, ma ci stanno lavorando

Come Abilitarlo

La configurazione è semplice:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net10.0-ios;net10.0-maccatalyst</TargetFrameworks>
    <OutputType>Exe</OutputType>
    <UseMaui>true</UseMaui>

    <PublishAot>true</PublishAot>
    <PublishTrimmed>true</PublishTrimmed>
    <TrimMode>full</TrimMode>
  </PropertyGroup>
</Project>

Attenzione alla Reflection

NativeAOT elimina il supporto per la reflection dinamica, quindi bisogna fornire annotazioni esplicite al trimmer. Non è complicato, ma richiede attenzione:

using System.Diagnostics.CodeAnalysis;

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class ProdottoViewModel
{
    public string Nome { get; set; }
    public decimal Prezzo { get; set; }
    public string Descrizione { get; set; }
}

public class ServizioProdotti
{
    [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods,
                       typeof(ProdottoViewModel))]
    public List<ProdottoViewModel> CaricaProdotti()
    {
        return new List<ProdottoViewModel>();
    }
}

Per casi più complessi, c'è sempre il file TrimmerRoots.xml per preservare tipi specifici dal trimming.

Un Consiglio sulle Librerie

Prima di abilitare NativeAOT, verificate che le librerie di terze parti che usate non facciano uso intensivo di reflection e forniscano annotazioni per il trimming. Un buon approccio è abilitare prima solo il trimming senza AOT completo, testare, e poi procedere gradualmente.

CoreCLR Sperimentale su Android: Il Futuro è Qui

.NET MAUI 10 porta il supporto sperimentale per il runtime CoreCLR su Android, come alternativa al classico Mono. È una mossa significativa che anticipa la futura unificazione del runtime .NET su tutte le piattaforme.

Come Provarlo

Per chi vuole sperimentare, basta disabilitare Mono con una proprietà MSBuild:

<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
    <UseMonoRuntime>false</UseMonoRuntime>
</PropertyGroup>

Cosa Ci Guadagnate (Potenzialmente)

CoreCLR su Android porta diversi benefici:

  • JIT più performante — CoreCLR ha un compilatore JIT decisamente più avanzato
  • Comportamento più coerente con .NET su server e desktop
  • Garbage Collection migliore — GC più sofisticato e ottimizzato
  • Strumenti di debugging più avanzati

C'è un ma: le dimensioni dell'app aumentano perché CoreCLR è più grande di Mono, e alcuni strumenti di diagnostica runtime potrebbero essere incompleti.

Attenzione: È Sperimentale

Mettiamolo in chiaro: non usatelo in produzione. Possibili problemi di stabilità, funzionalità di diagnostica incomplete, e in generale tutti i caveat di una feature sperimentale. Microsoft incoraggia i test e il feedback, ma con le dovute cautele.

Detto questo, la comunità ha accolto la notizia con entusiasmo — e a ragione. L'unificazione del runtime è il passo logico successivo per eliminare le differenze di comportamento tra piattaforme.

Popover Modali su iOS e Mac Catalyst

.NET MAUI 10 aggiunge un platform-specific per visualizzare pagine modali come popover su iOS e Mac Catalyst. I popover sono un pattern UI comune sulle piattaforme Apple: mostrano contenuto modale in un pannello flottante ancorato a un elemento specifico dell'interfaccia.

A differenza dei modal tradizionali che occupano tutto lo schermo, i popover sono ancorati a un elemento UI, mostrano una freccia verso l'origine, si chiudono toccando fuori dall'area, e su iPad/Mac appaiono in overlay (su iPhone si adattano mostrando uno sheet).

Una funzionalità che migliora sensibilmente l'esperienza utente su iPad e Mac, offrendo un modo elegante per mostrare contenuto supplementare senza interrompere il flusso dell'app.

Guida Pratica alla Migrazione

Ok, tutto molto bello — ma come si migra in pratica a .NET MAUI 10? Ecco un approccio graduale che riduce i rischi al minimo.

Prima di Tutto: Valutate

Prima di toccare una riga di codice, controllate:

  • Pacchetti NuGet — tutti compatibili con .NET 10?
  • Binding nativi — funzionano ancora?
  • Custom renderer — ne avete? Potrebbero richiedere aggiornamenti
  • Uso di reflection — se puntate a NativeAOT, mappatelo tutto

Migrazione a Fasi

Il consiglio è procedere per fasi, testando dopo ciascuna:

<!-- Fase 1: Aggiorna il target framework -->
<PropertyGroup>
  <TargetFrameworks>net10.0-android;net10.0-ios;net10.0-maccatalyst</TargetFrameworks>
</PropertyGroup>

<!-- Fase 2: Abilita XAML Source Generation -->
<PropertyGroup>
  <MauiXamlInflator>SourceGenerator</MauiXamlInflator>
</PropertyGroup>

<!-- Fase 3: Abilita trimming -->
<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <TrimMode>partial</TrimMode>
</PropertyGroup>

<!-- Fase 4: Abilita NativeAOT -->
<PropertyGroup>
  <PublishAot>true</PublishAot>
  <TrimMode>full</TrimMode>
</PropertyGroup>

Configurare la Telemetria per Debug e Produzione

Un pattern che consiglio: differenziate la configurazione di telemetria tra sviluppo e produzione. In sviluppo volete tutti i dati possibili, in produzione solo quelli essenziali:

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder.UseMauiApp<App>();

        #if DEBUG
        ConfiguraTelemetriaDebug(builder.Services);
        #else
        ConfiguraTelemetriaProduzione(builder.Services);
        #endif

        return builder.Build();
    }

    private static void ConfiguraTelemetriaDebug(IServiceCollection services)
    {
        services.AddOpenTelemetry()
            .WithMetrics(metrics =>
            {
                metrics
                    .AddMeter("Microsoft.Maui")
                    .AddMeter("MiaApp")
                    .AddConsoleExporter();
            })
            .WithTracing(tracing =>
            {
                tracing
                    .AddSource("Microsoft.Maui")
                    .AddSource("MiaApp")
                    .SetSampler(new AlwaysOnSampler())
                    .AddConsoleExporter();
            });
    }

    private static void ConfiguraTelemetriaProduzione(IServiceCollection services)
    {
        services.AddOpenTelemetry()
            .WithMetrics(metrics =>
            {
                metrics
                    .AddMeter("MiaApp")
                    .AddOtlpExporter();
            })
            .WithTracing(tracing =>
            {
                tracing
                    .AddSource("MiaApp")
                    .SetSampler(new TraceIdRatioBasedSampler(0.1))
                    .AddOtlpExporter();
            });
    }
}

Cosa Testare

Un piano di test serio dovrebbe coprire:

  • Funzionalità — tutto funziona come prima?
  • Performance — misurate startup, dimensioni e prestazioni runtime
  • Compatibilità OS — testate su tutte le versioni supportate
  • Memoria — niente memory leak introdotti?
  • Stabilità — monitorate i crash, specialmente con NativeAOT

Conclusioni: .NET MAUI 10 Vale l'Aggiornamento?

Sì. Senza mezzi termini.

.NET MAUI 10 è la versione che molti di noi stavano aspettando. Non è una rivoluzione concettuale, ma un consolidamento serio che rende il framework finalmente maturo e competitivo. E a volte, è esattamente quello che serve.

I Numeri che Contano

  • Produttività — XAML Source Generation porta miglioramenti fino a 100x nei tempi di build in Debug
  • Dimensioni app — NativeAOT le riduce fino a 2.5 volte
  • Avvio — tempi dimezzati con NativeAOT
  • Osservabilità — integrazione con OpenTelemetry e Aspire per una visibilità senza precedenti
  • Qualità della vita — ShadowTypeConverter, OffColor, namespace globali, popover

Cosa Aspettarsi nel Futuro

Il team di .NET MAUI ha delineato diverse direzioni:

  • NativeAOT su Android — in arrivo, per portare gli stessi benefici su tutte le piattaforme
  • Runtime unificato CoreCLR — per eliminare le differenze tra piattaforme
  • Ulteriori ottimizzazioni XAML e Hot Reload potenziato
  • Maggiore integrazione Blazor Hybrid per scenari web-to-native

Il 2026 sarà un anno critico per MAUI: dovrà dimostrare miglioramenti qualitativi sostenuti e competitività con Flutter e React Native. Con questa release, però, la direzione è quella giusta.

Il mio consiglio? Non aspettate. Iniziate a pianificare la migrazione adesso — i benefici in termini di prestazioni e produttività sono troppo significativi per restare indietro.

Sull'Autore Editorial Team

Our team of expert writers and editors.