Migrer de ZXing.Net vers IronBarcode
Ce guide décrit la migration complète de ZXing .NET vers Code-barres IronBarcode pour les applications .NET qui lisent et génèrent des codes-barres. Il aborde la suppression du package principal de ZXing.Net et des packages de liaison, l'élimination des contournements de PdfiumViewer là où ils sont présents, et le remplacement de chaque instanciation d'BarcodeReader avec l'API statique d'IronBarcode. Chaque section comprend des exemples de code avant et après, tirés des modèles les plus couramment utilisés dans les intégrations ZXing .NET .
Pourquoi migrer depuis ZXing .NET ?
ZXing .NET a rendu de précieux services à la communauté .NET pendant plus d'une décennie en tant que bibliothèque de codes-barres gratuite sous Apache 2.0. Cependant, plusieurs contraintes architecturales se transforment en coûts opérationnels à mesure que les applications gagnent en envergure ou en complexité.
Propriété de la sécurité des threads : L'BarcodeReader de ZXing.Net est un objet avec état. La documentation de la bibliothèque elle-même indique que les instances ne doivent pas être partagées entre les threads. En pratique, cela signifie que chaque chemin de traitement concurrent — chaque action de contrôleur gérant des requêtes simultanées, chaque tâche d'un lot parallèle — doit allouer, configurer et supprimer son propre lecteur. À mesure que le volume des requêtes augmente, ce modèle d'allocation engendre une pression mesurable sur la mémoire. L'alternative ThreadLocal<BarcodeReader> réduit la fréquence d'allocation mais introduit sa propre complexité de désallocation. Dans les deux cas, la correction en cas de concurrence est le problème de l'appelant, et non une garantie fournie par la bibliothèque.
Risque de spécification de format : ZXing.Net nécessite que l'reader.Options.PossibleFormats soit rempli avant chaque opération de décodage. Un code-barres dans un format non présent dans cette liste renvoie null — pas d'exception, pas d'avertissement, pas d'indication qu'un code-barres était présent mais non reconnu. Pour les applications qui reçoivent des documents de partenaires externes, ce comportement silencieusement raté est un risque de fiabilité : une commande mal expédiée, un enregistrement de patient raté, ou une entrée d'audit qui ne s'écrit jamais peut tous provenir d'une liste de formats configurée pour une exigence précédente et jamais mise à jour.
Lacune en matière de traitement PDF : ZXing .NET ne lit que les images bitmap. Lorsque les documents sources sont des PDF (factures, manifestes d'expédition, certificats de conformité), les appelants doivent intégrer une bibliothèque de rendu PDF distincte (PdfiumViewer étant la plus courante), implémenter une boucle d'énumération des pages, configurer le DPI, gérer les fichiers temporaires et gérer le nettoyage en cas de succès ou d'échec. Il s'agit de 30 à 50 lignes de code d'infrastructure par intégration qui existent uniquement pour convertir ce que ZXing .NET ne peut pas lire (PDF) en ce qu'il peut (images bitmap). Cette infrastructure possède ses propres dépendances, ses propres exigences de déploiement et ses propres modes de défaillance.
Fragmentation de la liaison de plateforme : la capacité de chargement d'images de ZXing.Net est répartie entre des packages de liaison spécifiques à chaque plateforme. La liaison Windows utilise System.Drawing.Bitmap; la liaison multiplateforme utilise SixLabors.ImageSharp avec un paramètre de type générique différent et une directive using différente. Un projet qui commence sur Windows et qui est plus tard containerisé sur Linux doit changer ses références NuGet et son code de chargement d'image. Deux chemins d'exécution pour une même opération augmentent la surface d'apparition de bogues et compliquent les modifications futures de la couche de numérisation.
Le problème fondamental
L'illustration la plus claire de l'architecture ZXing .NET est l'écart entre un appel monothread et un appel concurrent. Dans ZXing .NET, le traitement concurrent nécessite la création d'un objet lecteur complet pour chaque opération parallèle :
// ZXing.Net: full reader instantiation and configuration on every parallel task
Parallel.ForEach(files, file =>
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(file);
var result = reader.Decode(bitmap);
if (result != null)
processed[file] = result.Text;
});Imports ZXing
Imports System.Drawing
Imports System.Threading.Tasks
Parallel.ForEach(files, Sub(file)
Dim reader As New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
}
Using bitmap As New Bitmap(file)
Dim result = reader.Decode(bitmap)
If result IsNot Nothing Then
processed(file) = result.Text
End If
End Using
End Sub)IronBarcode supprime entièrement l'objet. L'appel statique est identique, qu'il s'exécute sur un seul thread ou sur une centaine :
// IronBarcode: static call, same code for single-threaded and concurrent use
Parallel.ForEach(files, file =>
{
var result = BarcodeReader.Read(file).FirstOrDefault();
if (result != null)
processed[file] = result.Value;
});Imports IronBarCode
Imports System.Threading.Tasks
Parallel.ForEach(files, Sub(file)
Dim result = BarcodeReader.Read(file).FirstOrDefault()
If result IsNot Nothing Then
processed(file) = result.Value
End If
End Sub)Comparaison des fonctionnalités : Code-barres IronBarcode vs ZXing .NET
| Fonction | ZXing.Net | Code-barres IronBarcode |
|---|---|---|
| Licence | Apache 2.0 (gratuit) | Commercial |
| Sécurité des threads | Non thread-safe — une nouvelle instance par thread est requise. | API statique sécurisée pour les threads |
| Détection de format | Manuel — liste PossibleFormats requise | Automatique — Plus de 50 formats |
| Lecture de PDF | Non — nécessite PdfiumViewer ou un logiciel similaire | Natif — appel de méthode unique |
| Support de la plateforme | Des packages de liaison distincts par plateforme | Un seul package, toutes plateformes |
| Plusieurs codes-barres par image | Oui — DecodeMultiple | Oui — comportement par défaut |
| Génération de codes-barres | Retourne Bitmap, nécessite un enregistrement manuel | API fluide avec sortie intégrée |
| Prise en charge des logos QR Code | Non | Oui |
| Contrôle des couleurs du code QR | Non | Oui |
| Récupération de codes-barres endommagés | drapeau TryHarder | Correction d'images basée sur l'apprentissage automatique |
| Dépendances supplémentaires de Docker | Peut nécessiter libgdiplus | None |
| Assistance SLA commerciale | Non | Oui |
| Packages NuGet requis | 2–3 (noyau + liaison + ImageSharp optionnel) | 1 |
Démarrage rapide
Étape 1 : Supprimer les packages ZXing .NET
Supprimez tous les packages ZXing .NET et associés du projet :
dotnet remove package ZXing.Net
dotnet remove package ZXing.Net.Bindings.Windows.Compatibility
dotnet remove package ZXing.Net.Bindings.ImageSharp
dotnet remove package PdfiumViewer
Si les binaires natifs de PdfiumViewer étaient installés en tant que paquet séparé :
dotnet remove package PdfiumViewer.Native.x64.v8-xfa
Si le Dockerfile contient apt-get install -y libgdiplus — ajouté pour supporter System.Drawing via la liaison Windows sur Linux — cette ligne peut être supprimée après la migration.
Étape 2 : Installer IronBarcode
dotnet add package IronBarcode
Aucun package de liaison supplémentaire ni dépendance spécifique à la plateforme n'est requis. Le même package NuGet fonctionne sous Windows, Linux, macOS et dans les conteneurs Docker. Pour plus de détails sur le déploiement, le guide d'installation d' Code-barres IronBarcode pour Docker et Linux détaille le modèle exact de Dockerfile.
Étape 3 : Mise à jour des espaces de noms et initialisation de la licence
Supprimez tous les espaces de noms liés à ZXing de chaque fichier utilisant des opérations de code-barres :
// Remove all of these:
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using PdfiumViewer;
// Add this single import:
using IronBarCode;Imports IronBarCodeAjouter l'initialisation de la licence au démarrage de l'application, avant toute opération sur les codes-barres :
// Program.cs or Startup.cs — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";' Program.vb or Startup.vb — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"La clé de licence est une chaîne simple qui peut être chargée à partir d'une variable d'environnement, appsettings.json, ou d'un gestionnaire de secrets. Aucun fichier à localiser, aucun chemin à configurer.
Exemples de migration de code
Lecture d'un seul code-barres à partir d'une image
Cet exemple remplace le modèle d'utilisation le plus courant de ZXing .NET : instancier un lecteur, configurer la liste des formats, charger une image bitmap et décoder.
Approche ZXing .NET :
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;
public string ReadSingleBarcode(string imagePath)
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
};
using var bitmap = new Bitmap(imagePath);
var result = reader.Decode(bitmap);
return result?.Text ?? string.Empty;
}Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Public Function ReadSingleBarcode(imagePath As String) As String
Dim reader = New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.EAN_13
}
Using bitmap As New Bitmap(imagePath)
Dim result = reader.Decode(bitmap)
Return If(result?.Text, String.Empty)
End Using
End FunctionApproche IronBarcode :
using IronBarCode;
public string ReadSingleBarcode(string imagePath)
{
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
return result?.Value ?? string.Empty;
}Imports IronBarCode
Public Function ReadSingleBarcode(imagePath As String) As String
Dim result = BarcodeReader.Read(imagePath).FirstOrDefault()
Return If(result?.Value, String.Empty)
End FunctionLa liste de formats, l'allocation Bitmap et le bloc using sont tous supprimés. Code-barres IronBarcode accepte directement un chemin de fichier et détecte automatiquement tous les formats pris en charge. La propriété qui renvoyait auparavant la chaîne décodée était result.Text dans ZXing.Net; elle est result.Value dans IronBarcode.
Lecture de tous les codes-barres à partir d'une image
Cet exemple remplace DecodeMultiple, qui dans ZXing.Net nécessite une liste de formats exhaustive pour éviter les manques silencieux.
Approche ZXing .NET :
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;
public List<string> ReadAllBarcodes(string imagePath)
{
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.CODE_39,
BarcodeFormat.EAN_13,
BarcodeFormat.EAN_8,
BarcodeFormat.UPC_A,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.PDF_417
};
reader.Options.TryHarder = true;
using var bitmap = new Bitmap(imagePath);
var results = reader.DecodeMultiple(bitmap);
return results?.Select(r => r.Text).ToList() ?? new List<string>();
}Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
Dim reader = New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.CODE_39,
BarcodeFormat.EAN_13,
BarcodeFormat.EAN_8,
BarcodeFormat.UPC_A,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.PDF_417
}
reader.Options.TryHarder = True
Using bitmap As New Bitmap(imagePath)
Dim results = reader.DecodeMultiple(bitmap)
Return If(results?.Select(Function(r) r.Text).ToList(), New List(Of String)())
End Using
End FunctionApproche IronBarcode :
using IronBarCode;
public List<string> ReadAllBarcodes(string imagePath)
{
return BarcodeReader.Read(imagePath)
.Select(r => r.Value)
.ToList();
}Imports IronBarCode
Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
Return BarcodeReader.Read(imagePath) _
.Select(Function(r) r.Value) _
.ToList()
End FunctionBarcodeReader.Read renvoie toujours une collection et ne renvoie jamais null, éliminant ainsi la garde de null sur le résultat. Pour ajuster l'équilibre précision-vitesse, consultez le guide des options de vitesse de lecture, qui couvre l'énumération ReadingSpeed sans restreindre la portée du format.
Traitement par lots simultané
Cet exemple illustre le plus directement la différence en matière de sécurité des threads. ZXing .NET nécessite un nouveau lecteur pour chaque opération parallèle ; Code-barres IronBarcode utilise le même appel statique quel que soit le niveau de concurrence.
Approche ZXing .NET :
using ZXing;
using ZXing.Windows.Compatibility;
using System.Collections.Concurrent;
using System.Drawing;
public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
var output = new ConcurrentDictionary<string, string>();
Parallel.ForEach(filePaths, new ParallelOptions { MaxDegreeOfParallelism = 4 }, file =>
{
// ZXing.Net is not thread-safe — a new reader is required per parallel operation
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128
};
using var bitmap = new Bitmap(file);
var result = reader.Decode(bitmap);
if (result != null)
output[file] = result.Text;
});
return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Collections.Concurrent
Imports System.Drawing
Public Function ProcessBatch(filePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
Dim output = New ConcurrentDictionary(Of String, String)()
Parallel.ForEach(filePaths, New ParallelOptions With {.MaxDegreeOfParallelism = 4}, Sub(file)
' ZXing.Net is not thread-safe — a new reader is required per parallel operation
Dim reader = New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128
}
Using bitmap As New Bitmap(file)
Dim result = reader.Decode(bitmap)
If result IsNot Nothing Then
output(file) = result.Text
End If
End Using
End Sub)
Return output.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
End FunctionApproche IronBarcode :
using IronBarCode;
using System.Collections.Concurrent;
public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
var output = new ConcurrentDictionary<string, string>();
var options = new BarcodeReaderOptions { MaxParallelThreads = 4 };
Parallel.ForEach(filePaths, file =>
{
var result = BarcodeReader.Read(file, options).FirstOrDefault();
if (result != null)
output[file] = result.Value;
});
return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}Imports IronBarCode
Imports System.Collections.Concurrent
Public Function ProcessBatch(filePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
Dim output = New ConcurrentDictionary(Of String, String)()
Dim options = New BarcodeReaderOptions With {.MaxParallelThreads = 4}
Parallel.ForEach(filePaths, Sub(file)
Dim result = BarcodeReader.Read(file, options).FirstOrDefault()
If result IsNot Nothing Then
output(file) = result.Value
End If
End Sub)
Return output.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
End FunctionIl n'existe aucune instance de lecteur à protéger ou à isoler. Pour les modèles de pipeline asynchrones et la configuration du nombre de threads, consultez le guide de lecture de codes-barres asynchrones et multithreadés .
Extraction des codes-barres d'un PDF
Cet exemple remplace la boucle de rendu PdfiumViewer. Si l'intégration existante utilisait Ghostscript ou iText au lieu de PdfiumViewer, le bloc avant aura un aspect différent en détail mais structurellement identique : une boucle d'énumération de pages alimentant des bitmaps à ZXing.Net.
Approche ZXing .NET :
using ZXing;
using ZXing.Windows.Compatibility;
using PdfiumViewer;
using System.Drawing;
using System.Drawing.Imaging;
public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
var collected = new List<string>();
var reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.PDF_417
};
using var document = PdfDocument.Load(pdfPath);
for (int page = 0; page < document.PageCount; page++)
{
string temp = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
try
{
using var rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi);
rendered.Save(temp, ImageFormat.Png);
using var bmp = new Bitmap(temp);
var decoded = reader.DecodeMultiple(bmp);
if (decoded != null)
collected.AddRange(decoded.Select(d => d.Text));
}
finally
{
if (File.Exists(temp))
File.Delete(temp);
}
}
return collected;
}Imports ZXing
Imports ZXing.Windows.Compatibility
Imports PdfiumViewer
Imports System.Drawing
Imports System.Drawing.Imaging
Public Function ExtractBarcodesFromPdf(pdfPath As String) As List(Of String)
Dim collected As New List(Of String)()
Dim reader As New BarcodeReader()
reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
BarcodeFormat.QR_CODE,
BarcodeFormat.CODE_128,
BarcodeFormat.PDF_417
}
Using document = PdfDocument.Load(pdfPath)
For page As Integer = 0 To document.PageCount - 1
Dim temp As String = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png")
Try
Using rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi)
rendered.Save(temp, ImageFormat.Png)
Using bmp As New Bitmap(temp)
Dim decoded = reader.DecodeMultiple(bmp)
If decoded IsNot Nothing Then
collected.AddRange(decoded.Select(Function(d) d.Text))
End If
End Using
End Using
Finally
If File.Exists(temp) Then
File.Delete(temp)
End If
End Try
Next
End Using
Return collected
End FunctionApproche IronBarcode :
using IronBarCode;
public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
return BarcodeReader.Read(pdfPath)
.Select(r => r.Value)
.ToList();
}Imports IronBarCode
Public Function ExtractBarcodesFromPdf(pdfPath As String) As List(Of String)
Return BarcodeReader.Read(pdfPath) _
.Select(Function(r) r.Value) _
.ToList()
End FunctionLa dépendance à PdfiumViewer, la boucle de rendu de la page, la configuration DPI, la création de fichiers temporaires et le bloc de nettoyage sont tous supprimés. Code-barres IronBarcode lit nativement les codes-barres des fichiers PDF et traite automatiquement toutes les pages.
Générer un code-barres
Le générateur ZXing.Net renvoie un Bitmap que les appelants doivent enregistrer en utilisant System.Drawing.Imaging. Code-barres IronBarcode renvoie un GeneratedBarcode avec des méthodes de sortie intégrées.
Approche ZXing .NET :
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing;
using System.Drawing.Imaging;
public void WriteCode128(string content, string outputPath)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Width = 400,
Height = 120,
Margin = 10
}
};
using var bitmap = writer.Write(content);
bitmap.Save(outputPath, ImageFormat.Png);
}Imports ZXing
Imports ZXing.Common
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Imports System.Drawing.Imaging
Public Sub WriteCode128(content As String, outputPath As String)
Dim writer = New BarcodeWriter With {
.Format = BarcodeFormat.CODE_128,
.Options = New EncodingOptions With {
.Width = 400,
.Height = 120,
.Margin = 10
}
}
Using bitmap = writer.Write(content)
bitmap.Save(outputPath, ImageFormat.Png)
End Using
End SubApproche IronBarcode :
using IronBarCode;
public void WriteCode128(string content, string outputPath)
{
BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.SaveAsPng(outputPath);
}Imports IronBarCode
Public Sub WriteCode128(content As String, outputPath As String)
BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.SaveAsPng(outputPath)
End SubSi une sortie binaire est nécessaire au lieu de l'enregistrement dans un fichier, ToPngBinaryData() et ToJpegBinaryData() sont disponibles sur l'objet GeneratedBarcode renvoyé, sans aucune plomberie MemoryStream.
Référence de mappage de l'API ZXing .NET vers IronBarcode
| ZXing.Net | Code-barres IronBarcode | Notes |
|---|---|---|
new BarcodeReader() | Statique — aucune instance | BarcodeReader.Read(...) est un appel statique |
reader.Options.PossibleFormats = nouvelle liste<BarcodeFormat> { ... } | Pas nécessaire | La détection automatique couvre plus de 50 formats |
reader.Options.TryHarder = true | Speed = ReadingSpeed.Balanced | Ajustement de la précision via BarcodeReaderOptions |
reader.Decode(bitmap) | BarcodeReader.Read(imagePath).FirstOrDefault() | Passer le chemin du fichier — aucune construction Bitmap n'est nécessaire |
reader.DecodeMultiple(bitmap) | BarcodeReader.Read(imagePath) | Renvoie toujours une collection ; never null |
result.Text | result.Value | Propriété renommée |
result.BarcodeFormat | result.Format | Propriété renommée |
BarcodeFormat.QR_CODE | BarcodeEncoding.QRCode | Changement de convention d'appellation des énumérations |
BarcodeFormat.CODE_128 | BarcodeEncoding.Code128 | Changement de convention d'appellation des énumérations |
BarcodeFormat.EAN_13 | BarcodeEncoding.EAN13 | Changement de convention d'appellation des énumérations |
BarcodeFormat.DATA_MATRIX | BarcodeEncoding.DataMatrix | Changement de convention d'appellation des énumérations |
BarcodeFormat.PDF_417 | BarcodeEncoding.PDF417 | Changement de convention d'appellation des énumérations |
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } } | BarcodeWriter.CreateBarcode(data, encoding) | Usine statique, aucun objet d'options |
writer.Write(data) renvoie Bitmap | .SaveAsPng(path) / .ToPngBinaryData() | Sortie intégrée sur GeneratedBarcode |
EncodingOptions { Width, Height } | .ResizeTo(width, height) | Méthode de dimensionnement fluide |
| Prise en charge des fichiers PDF non disponible | BarcodeReader.Read("file.pdf") | Prise en charge native du format PDF, toutes les pages |
Problèmes de migration courants et solutions
Problème 1 : Modèles d'instanciation de BarcodeReader
ZXing.Net : Les appelants créent un new BarcodeReader(), définissent reader.Options.PossibleFormats, chargent un Bitmap, appellent reader.Decode(bitmap) ou reader.DecodeMultiple(bitmap), et lisent result.Text.
Solution : Supprimez complètement l'instanciation. Remplacez le modèle complet par un appel statique :
// Before: reader creation + format config + bitmap + decode + result.Text
// After:
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
var value = result?.Value ?? string.Empty;' Before: reader creation + format config + bitmap + decode + result.Text
' After:
Dim result = BarcodeReader.Read(imagePath).FirstOrDefault()
Dim value = If(result?.Value, String.Empty)Recherchez la base de code pour new BarcodeReader() pour trouver chaque instance. Chaque élément est supprimé, non remanié.
Problème 2 : Suppression du bloc PossibleFormats
ZXing .NET: Chaque appel de décodage est précédé d'un reader.Options.PossibleFormats = nouvelle liste<BarcodeFormat> { ... }affectation. Ces listes sont souvent longues et spécifiques à chaque projet.
Solution : Supprimez chaque bloc d'affectation PossibleFormats dans son intégralité. Code-barres IronBarcode effectue une détection automatique du format ; Aucune liste de format n'est acceptée ni requise. Si le drapeau TryHarder = true était défini en même temps que la liste des formats, remplacez-le par Speed = ReadingSpeed.Balanced sur un objet BarcodeReaderOptions si un ajustement de précision est nécessaire.
Problème 3 : Nettoyage du package de liaison
ZXing.Net : Les projets utilisant ZXing.Net.Bindings.Windows.Compatibility ont du code référencé System.Drawing.Bitmap comme type d'entrée. Les projets utilisant ZXing.Net.Bindings.ImageSharp font référence à SixLabors.ImageSharp.Image<Rgba32>. Les deux modèles cessent de fonctionner après la suppression des paquets de liaison.
Solution : Supprimez les deux packages de liaison et remplacez tout le code de chargement d'images. L'BarcodeReader.Read d'IronBarcode accepte une chaîne de chemin de fichier, un byte[], un Stream, ou un Uri — aucune construction Bitmap ou Image<t> n'est nécessaire. Les imports using System.Drawing; restants qui existaient uniquement pour le chargement Bitmap peuvent également être supprimés.
Problème 4 : conversion de result.Text en result.Value
ZXing.Net : La valeur du code-barres décodée est accessible via result.Text. Le format du code-barres est accessible via result.BarcodeFormat.
Solution : Remplacez result.Text par result.Value et result.BarcodeFormat par result.Format dans toute la base de code. Les deux changements sont des renommages de propriétés simples sans différence de comportement.
Liste de contrôle de migration ZXing .NET
Tâches préalables à la migration
Avant d'apporter des modifications, vérifiez le code source afin de trouver toutes les références à ZXing .NET :
grep -r "using ZXing" --include="*.cs" .
grep -r "new BarcodeReader" --include="*.cs" .
grep -r "PossibleFormats" --include="*.cs" .
grep -r "BarcodeFormat\." --include="*.cs" .
grep -r "reader\.Decode\|reader\.DecodeMultiple" --include="*.cs" .
grep -r "result\.Text\|result\.BarcodeFormat" --include="*.cs" .
grep -r "new BarcodeWriter\|writer\.Write\|EncodingOptions" --include="*.cs" .
grep -r "PdfiumViewer\|PdfDocument\.Load" --include="*.cs" .
grep -r "using System\.Drawing" --include="*.cs" .
Documentez quels fichiers font référence aux packages de liaison ZXing (Windows vs ImageSharp) et notez où System.Drawing.Bitmap est utilisé uniquement pour l'entrée ZXing. Vérifiez le Dockerfile (si présent) pour l'installation de libgdiplus.
Tâches de mise à jour du code
- Supprimez les packages NuGet
ZXing.Net,ZXing.Net.Bindings.Windows.Compatibility,ZXing.Net.Bindings.ImageSharp, etPdfiumViewer - Installez le package NuGet
IronBarcode - Ajoutez
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";au démarrage de l'application - Remplacez toutes les importations
using ZXing*etusing SixLabors.ImageSharp*parusing IronBarCode; - Supprimez chaque instanciation
new BarcodeReader() - Supprimez chaque bloc
reader.Options.PossibleFormats = ... - Remplacez
reader.Decode(bitmap)parBarcodeReader.Read(imagePath).FirstOrDefault() - Remplacez
reader.DecodeMultiple(bitmap)parBarcodeReader.Read(imagePath) - Remplacez
result.Textparresult.Value - Remplacez
result.BarcodeFormatparresult.Format - Mettez à jour les références d'énumération
BarcodeFormat.Xpar les équivalentsBarcodeEncoding.X - Remplacez
new BarcodeWriter { Format = ..., Options = new EncodingOptions { ... } }withBarcodeWriter.CreateBarcode(data, encoding).ResizeTo(w, h) - Remplacez
writer.Write(data)+bitmap.Save(...)par.SaveAsPng(path)ou.ToPngBinaryData() - Supprimez toutes les importations
using System.Drawing;qui existaient uniquement pour le chargement des bitmaps ZXing.Net - Supprimez la boucle de rendu de page PdfiumViewer partout où elle était implémentée comme solution de contournement pour les PDF.
- Supprimez
libgdiplusdu Dockerfile si elle a été ajoutée pour supporterSystem.Drawingsur Linux
Test de post-migration
- Vérifiez que tous les formats de codes-barres que l'application était précédemment configurée pour détecter sont bien reconnus.
- Testez avec des images contenant des formats de codes-barres qui étaient auparavant exclus de la liste
PossibleFormats, pour confirmer que la détection automatique les repère - Exécutez les chemins de traitement concurrents sous charge et vérifiez l'absence de conditions de concurrence ou de résultats nuls.
- Si l'application a traité les PDF via PdfiumViewer, veuillez fournir les mêmes fichiers PDF et vérifier que les valeurs des codes-barres correspondent.
- Vérifiez que les codes-barres générés (Code 128, code QR, etc.) présentent le format et les dimensions corrects.
- Sur les déploiements Linux ou Docker, confirmez que la lecture d'image et la lecture PDF fonctionnent sans
libgdiplus - Exécutez la Suite de tests complète et comparez les résultats à la référence avant migration.
Principaux avantages de la migration vers IronBarcode
Suppression des contraintes liées à la sécurité des threads : l'API statique d'IronBarcode supprime entièrement le modèle d'instance par thread. Il n'y a pas de lecteur à instancier, pas de liste de formats à configurer par thread, et pas de pool ThreadLocal à gérer. Le même appel est correct aussi bien dans les environnements monothread que dans les environnements hautement concurrents, et la correction de la concurrence est assurée par la bibliothèque plutôt que déléguée à chaque appelant.
Détection automatique du format : La suppression de la liste PossibleFormats élimine la catégorie des échecs silencieux lorsque les documents contiennent des formats de codes-barres qui n'ont pas été anticipés lors du développement. Les applications qui traitent des documents provenant de partenaires externes ou qui fonctionnent avec des normes de codes-barres en constante évolution n'ont plus besoin de maintenir une liste de formats pour rester fiables.
Traitement PDF natif : La boucle de rendu de PdfiumViewer — son énumération des pages, sa configuration DPI, le cycle de vie des fichiers temporaires et son code de nettoyage — est entièrement supprimée. Les applications qui nécessitaient auparavant deux bibliothèques (ZXing .NET et un moteur de rendu PDF) pour traiter un code-barres PDF n'en utilisent désormais qu'une seule. La réduction des dépendances déployées simplifie à la fois la compilation et la surface de déploiement.
Package unique multiplateforme : la distinction entre les packages de liaison pour les déploiements Windows et Linux est éliminée. Le même appel BarcodeReader.Read(path) se compile et se comporte de manière identique sur toutes les plateformes cibles, éliminant le besoin de conditionnels de plateforme dans le code de chargement d'images et simplifiant les flux de travail de développement multiplateformes et de containerisation.
Code d'infrastructure réduit : Le résultat le plus significatif de la migration est la suppression de l'infrastructure environnante — les blocs de chargement Bitmap, les listes de format, les boucles de rendu PdfiumViewer, les pools ThreadLocal — qui existaient dans les intégrations ZXing .NET non pas pour effectuer le traitement des codes-barres, mais pour satisfaire aux exigences architecturales de la bibliothèque. Ce qui subsiste après la migration, c'est la logique des codes-barres elle-même. Pour un contexte plus complet sur les taux de détection et les scénarios de numérisation, la comparaison entre les scanners ZXing .NET et IronBarcode offre une analyse plus large.

Curtis Chau détient un baccalauréat en informatique (Université de Carleton) et se spécialise dans le développement front-end avec expertise en Node.js, TypeScript, JavaScript et React. Passionné par la création d'interfaces utilisateur intuitives et esthétiquement plaisantes, Curtis aime travailler avec des frameworks modernes et créer des manuels bien structurés et visuellement attrayants.