Przejdź do treści stopki
FILMY

Jak odczytywać i skanować kody kreskowe w C# używając NET MAUI

Migrating fromInfragisticsBarCode to IronBarcode

Większość migracji kodów kreskowychInfragisticsma miejsce, ponieważ zespół potrzebował odczytu kodów kreskowych w projekcie, w którym dostępna była tylko generacja — WinForms, .NET Core lub dowolny projekt poza WPF — lub ponieważ sterowane zdarzeniami API czytnika WPF okazało się zbyt niestabilne do użytku produkcyjnego. Wzorzec mostka TaskCompletionSource, wspólne pole _result, które czyni równoczesne wywołania niebezpiecznymi, oraz ciche niepowodzenia spowodowane brakiem flag SymbologyType to częste powody, dla których zespoły szukają alternatyw.

Ten przewodnik przeprowadza użytkownika przez cały proces migracji: usuwanie pakietów kodów kreskowych Infragistics, zastępowanie kodu generującego i odczytującego zarówno w kontekście WinForms, jak i WPF oraz dodawanie funkcjonalności BarCode do typów projektów, w którychInfragisticsnie zapewniało żadnego wsparcia.

Szybki start

Krok 1: Usuń pakiety BarCode Infragistics

Usuń pakiety NuGet z kodami BarCodeInfragisticsze swojego projektu. W zależności od tego, jakich celów używałeś:

# WinForms generation package
dotnet remove package Infragistics.WinForms.Barcode

# WPF reading package
dotnet remove package Infragistics.WPF.BarcodeReader
# WinForms generation package
dotnet remove package Infragistics.WinForms.Barcode

# WPF reading package
dotnet remove package Infragistics.WPF.BarcodeReader
SHELL

Jeśli plik projektu odwołuje się do obu, usuń oba. Usunięcie pakietów związanych z kodami kreskowymi nie ma wpływu na licencjęInfragisticsUltimate, jeśli korzystasz z innych komponentów Infragistics.

Krok 2: Zainstaluj IronBarcode

dotnet add package IronBarcode
dotnet add package IronBarcode
SHELL

IronBarcode to pojedynczy pakiet, który działa w środowiskach WinForms, WPF, ASP.NET Core, konsoli, Blazor Server, Docker,Azure Functionsi AWS Lambda. Nie ma potrzeby tworzenia oddzielnych pakietów dla poszczególnych frameworków.

Krok 3: Aktualizacja przestrzeni nazw

Zamień przestrzenie nazw kodów kreskowychInfragisticsna IronBarCode (duże B, duże C):

// Remove these:
// using Infragistics.Win.UltraWinBarcode;
// using Infragistics.Controls.Barcodes;
// using System.Windows.Media.Imaging; // if only used for barcode BitmapImage loading

// Add this:
using IronBarCode;
// Remove these:
// using Infragistics.Win.UltraWinBarcode;
// using Infragistics.Controls.Barcodes;
// using System.Windows.Media.Imaging; // if only used for barcode BitmapImage loading

// Add this:
using IronBarCode;
Imports IronBarCode
$vbLabelText   $csharpLabel

Krok 4: Zainicjuj licencję

Dodaj inicjalizację licencji raz przy starcie aplikacji — Program.cs, App.xaml.cs lub twój rdzeń kompozycji DI:

IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode

IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Przykłady migracji kodu

Generowanie WinForms: UltraWinBarcode do BarcodeWriter

Wzorzec generacji WinForms mapuje się czysto na BarcodeWriter IronBarcode:

Przed (Infragistics WinForms):

using Infragistics.Win.UltraWinBarcode;

var barcode = new UltraWinBarcode();
barcode.Symbology = Symbology.Code128;
barcode.Data = "ITEM-12345";
barcode.SaveTo(outputPath);
using Infragistics.Win.UltraWinBarcode;

var barcode = new UltraWinBarcode();
barcode.Symbology = Symbology.Code128;
barcode.Data = "ITEM-12345";
barcode.SaveTo(outputPath);
Imports Infragistics.Win.UltraWinBarcode

Dim barcode As New UltraWinBarcode()
barcode.Symbology = Symbology.Code128
barcode.Data = "ITEM-12345"
barcode.SaveTo(outputPath)
$vbLabelText   $csharpLabel

Po (IronBarcode):

// NuGet: dotnet add package IronBarcode
using IronBarCode;

BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128)
             .SaveAsPng(outputPath);
// NuGet: dotnet add package IronBarcode
using IronBarCode;

BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128)
             .SaveAsPng(outputPath);
Imports IronBarCode

BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128) _
             .SaveAsPng(outputPath)
$vbLabelText   $csharpLabel

Wartość enum Symbology wInfragisticsprzechodzi do enum BarcodeEncoding, który jest parametrem dla CreateBarcode() zamiast przypisania właściwości. Dane stają się pierwszym argumentem. SaveTo() staje się .SaveAsPng(), .SaveAsJpeg(), .SaveAsSvg() lub .SaveAsPdf() w zależności od formatu wyjściowego.

Jeśli przed zapisaniem konieczne jest zmniejszenie rozmiaru BarCODE:

using IronBarCode;

BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128)
             .ResizeTo(400, 100)
             .SaveAsPng(outputPath);
using IronBarCode;

BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128)
             .ResizeTo(400, 100)
             .SaveAsPng(outputPath);
Imports IronBarCode

BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128) _
             .ResizeTo(400, 100) _
             .SaveAsPng(outputPath)
$vbLabelText   $csharpLabel

Czytanie sterowane zdarzeniami w WPF: klasa usługi w dwóch wierszach

Jest to najbardziej znacząca redukcja w ramach migracji. Wzorzec odczytuInfragisticsWPF wymaga klasy pełnej obsługi:

Przed (Infragistics WPF — ~35 wierszy):

using Infragistics.Controls.Barcodes;
using System.Windows.Media.Imaging;

private BarcodeReader _reader;
private TaskCompletionSource<string> _result;

public InfragisticsBarcodeService()
{
    _reader = new BarcodeReader();
    _reader.DecodeComplete += OnDecodeComplete;
}

public async Task<string> ReadBarcodeAsync(string imagePath)
{
    _result = new TaskCompletionSource<string>();

    var bitmap = new BitmapImage(new Uri(imagePath, UriKind.Absolute));

    _reader.SymbologyTypes = Symbology.Code128 |
                             Symbology.Code39 |
                             Symbology.QRCode |
                             Symbology.EAN8 |
                             Symbology.EAN13 |
                             Symbology.UpcA |
                             Symbology.Interleaved2Of5;

    _reader.Decode(bitmap);
    return await _result.Task;
}

private void OnDecodeComplete(object sender, ReaderDecodeArgs e)
{
    _result?.TrySetResult(e.Value ?? "No barcode found");
}

public void Dispose()
{
    if (_reader != null)
    {
        _reader.DecodeComplete -= OnDecodeComplete;
        _reader = null;
    }
}
using Infragistics.Controls.Barcodes;
using System.Windows.Media.Imaging;

private BarcodeReader _reader;
private TaskCompletionSource<string> _result;

public InfragisticsBarcodeService()
{
    _reader = new BarcodeReader();
    _reader.DecodeComplete += OnDecodeComplete;
}

public async Task<string> ReadBarcodeAsync(string imagePath)
{
    _result = new TaskCompletionSource<string>();

    var bitmap = new BitmapImage(new Uri(imagePath, UriKind.Absolute));

    _reader.SymbologyTypes = Symbology.Code128 |
                             Symbology.Code39 |
                             Symbology.QRCode |
                             Symbology.EAN8 |
                             Symbology.EAN13 |
                             Symbology.UpcA |
                             Symbology.Interleaved2Of5;

    _reader.Decode(bitmap);
    return await _result.Task;
}

private void OnDecodeComplete(object sender, ReaderDecodeArgs e)
{
    _result?.TrySetResult(e.Value ?? "No barcode found");
}

public void Dispose()
{
    if (_reader != null)
    {
        _reader.DecodeComplete -= OnDecodeComplete;
        _reader = null;
    }
}
Imports Infragistics.Controls.Barcodes
Imports System.Windows.Media.Imaging
Imports System.Threading.Tasks

Private _reader As BarcodeReader
Private _result As TaskCompletionSource(Of String)

Public Sub New()
    _reader = New BarcodeReader()
    AddHandler _reader.DecodeComplete, AddressOf OnDecodeComplete
End Sub

Public Async Function ReadBarcodeAsync(imagePath As String) As Task(Of String)
    _result = New TaskCompletionSource(Of String)()

    Dim bitmap As New BitmapImage(New Uri(imagePath, UriKind.Absolute))

    _reader.SymbologyTypes = Symbology.Code128 Or
                             Symbology.Code39 Or
                             Symbology.QRCode Or
                             Symbology.EAN8 Or
                             Symbology.EAN13 Or
                             Symbology.UpcA Or
                             Symbology.Interleaved2Of5

    _reader.Decode(bitmap)
    Return Await _result.Task
End Function

Private Sub OnDecodeComplete(sender As Object, e As ReaderDecodeArgs)
    _result?.TrySetResult(If(e.Value, "No barcode found"))
End Sub

Public Sub Dispose()
    If _reader IsNot Nothing Then
        RemoveHandler _reader.DecodeComplete, AddressOf OnDecodeComplete
        _reader = Nothing
    End If
End Sub
$vbLabelText   $csharpLabel

Po (IronBarcode — 2 wiersze):

using IronBarCode;

var results = BarcodeReader.Read(imagePath);
return results.FirstOrDefault()?.Value ?? "No barcode found";
using IronBarCode;

var results = BarcodeReader.Read(imagePath);
return results.FirstOrDefault()?.Value ?? "No barcode found";
Imports IronBarCode

Dim results = BarcodeReader.Read(imagePath)
Return If(results.FirstOrDefault()?.Value, "No barcode found")
$vbLabelText   $csharpLabel

Cała klasa usługi — zarządzanie instancją, okablowanie zdarzeń, TaskCompletionSource, ładowanie BitmapImage, Dispose() — zniknęły. BarcodeReader.Read() jest synchroniczna, statyczna i akceptuje bezpośrednio ścieżkę pliku w postaci ciągu znaków.

Jeśli zwracałbyś również typ symboliki:

using IronBarCode;

var results = BarcodeReader.Read(imagePath);
var first = results.FirstOrDefault();
if (first != null)
{
    Console.WriteLine($"Value: {first.Value}, Format: {first.Format}");
}
using IronBarCode;

var results = BarcodeReader.Read(imagePath);
var first = results.FirstOrDefault();
if (first != null)
{
    Console.WriteLine($"Value: {first.Value}, Format: {first.Format}");
}
Imports IronBarCode

Dim results = BarcodeReader.Read(imagePath)
Dim first = results.FirstOrDefault()
If first IsNot Nothing Then
    Console.WriteLine($"Value: {first.Value}, Format: {first.Format}")
End If
$vbLabelText   $csharpLabel

result.Value zastępuje e.Value. result.Format zastępuje e.Symbology.

Dodanie obsługi WinForms (wcześniej niemożliwe)

Jeśli pracowałeś nad projektem WinForms, który obsługiwał tylko generowanie, teraz w tym samym pakiecie dostępna jest również funkcja odczytu:

using IronBarCode;

// In a WinForms button handler or service method — same API as WPF or ASP.NET Core
var results = BarcodeReader.Read(imagePath);
foreach (var result in results)
{
    MessageBox.Show($"Found: {result.Value} ({result.Format})");
}
using IronBarCode;

// In a WinForms button handler or service method — same API as WPF or ASP.NET Core
var results = BarcodeReader.Read(imagePath);
foreach (var result in results)
{
    MessageBox.Show($"Found: {result.Value} ({result.Format})");
}
Imports IronBarCode

' In a WinForms button handler or service method — same API as WPF or ASP.NET Core
Dim results = BarcodeReader.Read(imagePath)
For Each result In results
    MessageBox.Show($"Found: {result.Value} ({result.Format})")
Next
$vbLabelText   $csharpLabel

Brak dodatkowych pakietów, żadnej specyficznej dla frameworka konfiguracji. To samo wywołanie BarcodeReader.Read() działa w WinForms jak i w WPF.

Punkt końcowyASP.NET Core(wcześniej niemożliwy)

Generowanie i odczytywanie BarCODE w kontrolerzeASP.NET Corenie było możliwe przy użyciu pakietów Infragistics. Dzięki IronBarcode:

using IronBarCode;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/barcode")]
public class BarcodeController : ControllerBase
{
    [HttpPost("read")]
    public IActionResult ReadBarcode(IFormFile imageFile)
    {
        using var stream = imageFile.OpenReadStream();
        var results = BarcodeReader.Read(stream);
        var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
        return Ok(values);
    }

    [HttpGet("generate")]
    public IActionResult GenerateBarcode([FromQuery] string data)
    {
        var bytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
                                 .ResizeTo(400, 100)
                                 .ToPngBinaryData();
        return File(bytes, "image/png");
    }
}
using IronBarCode;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/barcode")]
public class BarcodeController : ControllerBase
{
    [HttpPost("read")]
    public IActionResult ReadBarcode(IFormFile imageFile)
    {
        using var stream = imageFile.OpenReadStream();
        var results = BarcodeReader.Read(stream);
        var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
        return Ok(values);
    }

    [HttpGet("generate")]
    public IActionResult GenerateBarcode([FromQuery] string data)
    {
        var bytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
                                 .ResizeTo(400, 100)
                                 .ToPngBinaryData();
        return File(bytes, "image/png");
    }
}
Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc

<ApiController>
<Route("api/barcode")>
Public Class BarcodeController
    Inherits ControllerBase

    <HttpPost("read")>
    Public Function ReadBarcode(imageFile As IFormFile) As IActionResult
        Using stream = imageFile.OpenReadStream()
            Dim results = BarcodeReader.Read(stream)
            Dim values = results.Select(Function(r) New With {Key .Value = r.Value, Key .Format = r.Format.ToString()})
            Return Ok(values)
        End Using
    End Function

    <HttpGet("generate")>
    Public Function GenerateBarcode(<FromQuery> data As String) As IActionResult
        Dim bytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
                                  .ResizeTo(400, 100) _
                                  .ToPngBinaryData()
        Return File(bytes, "image/png")
    End Function
End Class
$vbLabelText   $csharpLabel

BarcodeReader.Read() akceptuje Stream bezpośrednio — nie ma potrzeby najpierw zapisywania uploadu na dysk.

Odczytywanie BarCodes z plików PDF

IronBarcode odczytuje kody kreskowe z dokumentów PDF w sposób natywny — nie wymaga oddzielnego pakietu:

using IronBarCode;

// Read all barcodes from every page of a PDF
var results = BarcodeReader.Read("document.pdf");
foreach (var result in results)
{
    Console.WriteLine($"Page {result.PageNumber}: {result.Value} ({result.Format})");
}
using IronBarCode;

// Read all barcodes from every page of a PDF
var results = BarcodeReader.Read("document.pdf");
foreach (var result in results)
{
    Console.WriteLine($"Page {result.PageNumber}: {result.Value} ({result.Format})");
}
Imports IronBarCode

' Read all barcodes from every page of a PDF
Dim results = BarcodeReader.Read("document.pdf")
For Each result In results
    Console.WriteLine($"Page {result.PageNumber}: {result.Value} ({result.Format})")
Next
$vbLabelText   $csharpLabel

Infragistics nie miał odpowiednika — odczyt BarCode'ów z plików PDF wymagał zewnętrznej konwersji stron PDF na obrazy przed skanowaniem.

Przetwarzanie wsadowe: od sekwencyjnego do równoległego

Przed (Infragistics — sekwencyjny, niezabezpieczony pod kątem współbieżności dla równoległości):

// Must process one at a time — shared _result field is not thread-safe
var service = new InfragisticsBarcodeService();
var results = new List<string>();

foreach (var file in imageFiles)
{
    var value = await service.ReadBarcodeAsync(file);
    results.Add(value);
}

service.Dispose();
// Must process one at a time — shared _result field is not thread-safe
var service = new InfragisticsBarcodeService();
var results = new List<string>();

foreach (var file in imageFiles)
{
    var value = await service.ReadBarcodeAsync(file);
    results.Add(value);
}

service.Dispose();
Imports System.Collections.Generic

' Must process one at a time — shared _result field is not thread-safe
Dim service As New InfragisticsBarcodeService()
Dim results As New List(Of String)()

For Each file In imageFiles
    Dim value As String = Await service.ReadBarcodeAsync(file)
    results.Add(value)
Next

service.Dispose()
$vbLabelText   $csharpLabel

Po (IronBarcode — równoległe, bezpieczne dla wątków):

using IronBarCode;

// Option 1: pass an array directly —IronBarcode handles parallelization internally
var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    MaxParallelThreads = 4
};

var results = BarcodeReader.Read(imageFiles.ToArray(), options);
foreach (var result in results)
{
    Console.WriteLine($"{result.Value} ({result.Format})");
}
using IronBarCode;

// Option 1: pass an array directly —IronBarcode handles parallelization internally
var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    MaxParallelThreads = 4
};

var results = BarcodeReader.Read(imageFiles.ToArray(), options);
foreach (var result in results)
{
    Console.WriteLine($"{result.Value} ({result.Format})");
}
Imports IronBarCode

' Option 1: pass an array directly —IronBarcode handles parallelization internally
Dim options As New BarcodeReaderOptions With {
    .Speed = ReadingSpeed.Balanced,
    .ExpectMultipleBarcodes = True,
    .MaxParallelThreads = 4
}

Dim results = BarcodeReader.Read(imageFiles.ToArray(), options)
For Each result In results
    Console.WriteLine($"{result.Value} ({result.Format})")
Next
$vbLabelText   $csharpLabel
using IronBarCode;
using System.Collections.Concurrent;

// Option 2: Parallel.ForEach — static BarcodeReader.Read is thread-safe
var allValues = new ConcurrentBag<string>();

Parallel.ForEach(imageFiles, file =>
{
    var results = BarcodeReader.Read(file);
    foreach (var r in results)
        allValues.Add(r.Value);
});
using IronBarCode;
using System.Collections.Concurrent;

// Option 2: Parallel.ForEach — static BarcodeReader.Read is thread-safe
var allValues = new ConcurrentBag<string>();

Parallel.ForEach(imageFiles, file =>
{
    var results = BarcodeReader.Read(file);
    foreach (var r in results)
        allValues.Add(r.Value);
});
Imports IronBarCode
Imports System.Collections.Concurrent

' Option 2: Parallel.ForEach — static BarcodeReader.Read is thread-safe
Dim allValues As New ConcurrentBag(Of String)()

Parallel.ForEach(imageFiles, Sub(file)
    Dim results = BarcodeReader.Read(file)
    For Each r In results
        allValues.Add(r.Value)
    Next
End Sub)
$vbLabelText   $csharpLabel

Usunięcie wzorca Dispose

Jeśli twój kod zawierał implementacje IDisposable wokółInfragisticsBarcodeReader, można je całkowicie usunąć. BarcodeReaderIronBarcode jest klasą statyczną. Nie ma żadnej instancji do utworzenia, żadnego obsługi zdarzeń do odłączenia i żadnego wywołania Dispose().

// Before: service registered as IDisposable in DI container
services.AddScoped<InfragisticsBarcodeService>(); // implements IDisposable

// After: no registration needed — use static method directly, or wrap in thin service if preferred
// services.AddScoped<IBarcodeService, IronBarcodeService>();
// Before: service registered as IDisposable in DI container
services.AddScoped<InfragisticsBarcodeService>(); // implements IDisposable

// After: no registration needed — use static method directly, or wrap in thin service if preferred
// services.AddScoped<IBarcodeService, IronBarcodeService>();
' Before: service registered as IDisposable in DI container
services.AddScoped(Of InfragisticsBarcodeService)() ' implements IDisposable

' After: no registration needed — use static method directly, or wrap in thin service if preferred
' services.AddScoped(Of IBarcodeService, IronBarcodeService)()
$vbLabelText   $csharpLabel

Prosta usługa typu thin wrapper do celów DI jest następująca:

using IronBarCode;

public class BarcodeService
{
    public IEnumerable<string> Read(string path)
        => BarcodeReader.Read(path).Select(r => r.Value);

    public byte[] Generate(string data, BarcodeEncoding encoding)
        => BarcodeWriter.CreateBarcode(data, encoding).ToPngBinaryData();
}
using IronBarCode;

public class BarcodeService
{
    public IEnumerable<string> Read(string path)
        => BarcodeReader.Read(path).Select(r => r.Value);

    public byte[] Generate(string data, BarcodeEncoding encoding)
        => BarcodeWriter.CreateBarcode(data, encoding).ToPngBinaryData();
}
Imports IronBarCode

Public Class BarcodeService
    Public Function Read(path As String) As IEnumerable(Of String)
        Return BarcodeReader.Read(path).Select(Function(r) r.Value)
    End Function

    Public Function Generate(data As String, encoding As BarcodeEncoding) As Byte()
        Return BarcodeWriter.CreateBarcode(data, encoding).ToPngBinaryData()
    End Function
End Class
$vbLabelText   $csharpLabel

Brak wstrzykiwania konstruktorów, brak Dispose(), brak zarządzania zdarzeniami.

Typowe problemy związane z migracją

Usunięto flagi typu symboliki

Właściwość SymbologyTypes w czytnikuInfragisticsWPF wymagała wskazania każdego formatu kodu kreskowego, który chciano obsługiwać.IronBarcode nie ma sobie równych — automatycznie wykrywa wszystkie ponad 50 obsługiwanych formatów przy każdym odczycie.

To ma ważny efekt uboczny: jeśli wcześniej konkretne formaty kodów kreskowych nie były wykrywane, ponieważ brakowało ich flagi SymbologyType na liście,IronBarcode teraz je znajdzie. W środowisku produkcyjnym mogą pojawić się wartości BarCode, które wcześniej były pomijane bez powiadomienia. To jest prawidłowe zachowanie — te barcody zawsze tam były.

Jeśli chcesz ograniczyć, które formaty są zwracane (ze względów wydajnościowych lub niejednoznaczności), BarcodeReaderOptions to obsługuje:

using IronBarCode;

var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = false
};

var results = BarcodeReader.Read(imagePath, options);
using IronBarCode;

var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = false
};

var results = BarcodeReader.Read(imagePath, options);
Imports IronBarCode

Dim options As New BarcodeReaderOptions With {
    .Speed = ReadingSpeed.Balanced,
    .ExpectMultipleBarcodes = False
}

Dim results = BarcodeReader.Read(imagePath, options)
$vbLabelText   $csharpLabel

Nie jest wymagane ładowanie obrazu bitmapowego

CzytnikInfragisticsWPF wymagał ładowania obrazów jako obiekty BitmapSource przez new BitmapImage(new Uri(path, UriKind.Absolute)).IronBarcode akceptuje bezpośrednio ciągi znaków ścieżek plików, tablice bajtów i strumienie:

// All of these work — no BitmapImage conversion needed
BarcodeReader.Read("path/to/image.png");
BarcodeReader.Read(File.ReadAllBytes("path/to/image.png"));
BarcodeReader.Read(File.OpenRead("path/to/image.png"));
// All of these work — no BitmapImage conversion needed
BarcodeReader.Read("path/to/image.png");
BarcodeReader.Read(File.ReadAllBytes("path/to/image.png"));
BarcodeReader.Read(File.OpenRead("path/to/image.png"));
' All of these work — no BitmapImage conversion needed
BarcodeReader.Read("path/to/image.png")
BarcodeReader.Read(File.ReadAllBytes("path/to/image.png"))
BarcodeReader.Read(File.OpenRead("path/to/image.png"))
$vbLabelText   $csharpLabel

Możesz usunąć wszelkie importy using System.Windows.Media.Imaging;, które były używane tylko do ładowania obrazów związanych z kodami kreskowymi.

Wzorzec TaskCompletionSource usunięty

Pole TaskCompletionSource<string>, które łączyło oparty na zdarzeniach callback DecodeComplete z kodem asynchronicznym, całkowicie zniknęło. BarcodeReader.Read() jest synchroniczna i zwraca swoje wyniki bezpośrednio.

Jeśli twój kod wywołujący był await service.ReadBarcodeAsync(path), możesz uprościć do:

// Before
var value = await service.ReadBarcodeAsync(imagePath);

// After
var value = BarcodeReader.Read(imagePath).FirstOrDefault()?.Value ?? "No barcode found";
// Before
var value = await service.ReadBarcodeAsync(imagePath);

// After
var value = BarcodeReader.Read(imagePath).FirstOrDefault()?.Value ?? "No barcode found";
$vbLabelText   $csharpLabel

Jeśli chcesz zachować interfejs asynchroniczny dla wywołujących na dalszym etapie bez blokowania wątku:

public Task<string> ReadBarcodeAsync(string imagePath)
{
    return Task.Run(() =>
    {
        var results = BarcodeReader.Read(imagePath);
        return results.FirstOrDefault()?.Value ?? "No barcode found";
    });
}
public Task<string> ReadBarcodeAsync(string imagePath)
{
    return Task.Run(() =>
    {
        var results = BarcodeReader.Read(imagePath);
        return results.FirstOrDefault()?.Value ?? "No barcode found";
    });
}
Option Strict On



Public Function ReadBarcodeAsync(imagePath As String) As Task(Of String)
    Return Task.Run(Function()
                        Dim results = BarcodeReader.Read(imagePath)
                        Return If(results.FirstOrDefault()?.Value, "No barcode found")
                    End Function)
End Function
$vbLabelText   $csharpLabel

Zmiany nazw właściwości

Infragistics IronBarcode
e.Value (w ReaderDecodeArgs) result.Value
e.Symbology (w ReaderDecodeArgs) result.Format
barcode.Data Pierwszy argument BarcodeWriter.CreateBarcode()
barcode.Symbology = Symbology.Code128 BarcodeEncoding.Code128 (parametr)
barcode.SaveTo(path) .SaveAsPng(path) / .SaveAsJpeg(path) / .SaveAsSvg(path)

Lista kontrolna migracji

Użyj tych wzorców grep, aby znaleźć wszystkie wystąpienia BARCODE-ówInfragisticsw swoim kodzie źródłowym:

# Namespace references
grep -r "Infragistics.WinForms.Barcode\|Infragistics.Win.UltraWinBarcode" --include="*.cs" .
grep -r "Infragistics.Controls.Barcodes" --include="*.cs" .
grep -r "Infragistics.WPF.BarcodeReader" --include="*.csproj" .

# WinForms generation types
grep -r "UltraWinBarcode" --include="*.cs" .
grep -r "Symbology\.Code" --include="*.cs" .
grep -r "barcode\.SaveTo(" --include="*.cs" .

# WPF reading types and patterns
grep -r "new BarcodeReader()" --include="*.cs" .
grep -r "DecodeComplete" --include="*.cs" .
grep -r "ReaderDecodeArgs" --include="*.cs" .
grep -r "SymbologyType\." --include="*.cs" .
grep -r "e\.Value\|ReaderDecodeArgs" --include="*.cs" .
grep -r "BitmapImage" --include="*.cs" .

# TaskCompletionSource usage (likely barcode-related if near above patterns)
grep -r "TaskCompletionSource" --include="*.cs" .
# Namespace references
grep -r "Infragistics.WinForms.Barcode\|Infragistics.Win.UltraWinBarcode" --include="*.cs" .
grep -r "Infragistics.Controls.Barcodes" --include="*.cs" .
grep -r "Infragistics.WPF.BarcodeReader" --include="*.csproj" .

# WinForms generation types
grep -r "UltraWinBarcode" --include="*.cs" .
grep -r "Symbology\.Code" --include="*.cs" .
grep -r "barcode\.SaveTo(" --include="*.cs" .

# WPF reading types and patterns
grep -r "new BarcodeReader()" --include="*.cs" .
grep -r "DecodeComplete" --include="*.cs" .
grep -r "ReaderDecodeArgs" --include="*.cs" .
grep -r "SymbologyType\." --include="*.cs" .
grep -r "e\.Value\|ReaderDecodeArgs" --include="*.cs" .
grep -r "BitmapImage" --include="*.cs" .

# TaskCompletionSource usage (likely barcode-related if near above patterns)
grep -r "TaskCompletionSource" --include="*.cs" .
SHELL

Przejrzyj wszystkie dopasowania:

  • Zamiany UltraWinBarcode: zamień na BarcodeWriter.CreateBarcode()
  • Bloki new BarcodeReader() + DecodeComplete: zamień na BarcodeReader.Read()
  • Listy flag SymbologyType: usuń całkowicie
  • Ładowania BitmapImage używane dla danych wejściowych z kodami kreskowymi: zamień na bezpośrednią ścieżkę/strumień/bajty
  • Ciało wywołań zwrotnych ReaderDecodeArgs e: wyodrębnij e.Valueresult.Value, e.Symbologyresult.Format
  • IDisposable w klasach usług kodów kreskowych: usuń, jeśli jedynym zasobem do wyrzucenia było _reader

Porównanie funkcji

Funkcja InfragisticsBarCode IronBarcode
Generowanie BarCode-ów w WinForms Tak (UltraWinBarcode) Tak
Odczytywanie BarCodes w WinForms Niedostępne Tak
Generowanie kodów kreskowych w WPF Tak (XamBarcode) Tak
Odczytywanie BarCode w WPF Tak (sterowane zdarzeniami) Tak (synchroniczne)
ASP.NET Core Niedostępne Tak
Konsola / Usługa robocza Niedostępne Tak
Docker / Linux Niedostępne Tak
Azure Functions Niedostępne Tak
Blazor Server Niedostępne Tak
Automatyczne wykrywanie formatowania Nie — flagi typu SymbologyType są wymagane Tak
Odczytywanie BarCodes z plików PDF Niedostępne Tak (język ojczysty)
Wielowątkowe odczyty Nie Tak
Odczyt partii (wbudowany) Nie Tak
Kontrola korekcji błędów QR Niedostępne Tak
Statyczne API (bez instancji) Nie Tak
Wymagana subskrypcja Suite pakietu Tak (Infragistics Ultimate, 2399 złotych+/rok) Nie
Licencja wieczysta Nie Tak — od 749 USD

Kluczowe korzyści po migracji

Odczyt kodów kreskowych w WinForms. Jeśli migracja była zainicjowana przez wymaganie odczytu w WinForms, to jest główny ostateczny wynik: BarcodeReader.Read(imagePath) kompiluje się i działa w WinForms bez żadnej dodatkowej konfiguracji.

Obsługa .NET Core i konsoli. Interfejsy API sieci Web, usługi działające w tle oraz narzędzia konsolowe mogą teraz zarówno generować, jak i odczytywać kody kreskowe przy użyciu tego samego pakietu. Jeśli dotychczas korzystałeś z oddzielnych łańcuchów narzędzi lub rozwiązań zastępczych dla tych typów projektów, teraz nie są one już potrzebne.

Brak standardowych obsługi zdarzeń. Usunięto obsługę DecodeComplete, mostek TaskCompletionSource, ładowanie BitmapImage i czyszczenie Dispose(). Pozostaje logika BarCode'ów.

Brak specyfikacji symbologii. Formatki, które wcześniej cicho się nie powiodły z powodu brakujących flag SymbologyType, będą teraz poprawnie wykryte. Automatyczne wykrywanie obejmuje ponad 50 formatów bez konieczności konfiguracji.

Ta sama klasa usługowa we wszystkich typach projektów. Pojedynczy wrapper BarcodeService używający BarcodeReader.Read() i BarcodeWriter.CreateBarcode() może być współdzielony w WinForms, WPF,ASP.NET Corei w dowolnym innym projekcie w rozwiązaniu. Nie należy stosować implementacji specyficznych dla danego frameworka.

Nie jest wymagana subskrypcjaInfragisticsUltimate wyłącznie w celu korzystania z funkcji kodów kreskowych. Jeśli obsługa kodów kreskowych była jedynym powodem, dla którego w ramach projektu wykupiono subskrypcjęInfragisticsUltimate, lub jeśli był to istotny czynnik decyzyjny,IronBarcode jest samodzielnym pakietem z opcjami licencji wieczystej, których cena zaczyna się od 749 USD dla jednego programisty.

Sama migracja jest mechaniczna, gdy już zlokalizujesz wszystkie miejsca użycia kodów kreskowych Infragistics. Najbardziej złożoną częścią jest zamiana klasy usługi WPF, a nawet to redukuje się do usunięcia klasy oraz zastąpienia wywołań przez BarcodeReader.Read(). Migracja generacji polega na zmianie nazw właściwości/metod w stosunku jeden do jednego. W zamian otrzymujesz jeden, spójny interfejs API, który działa w każdym potrzebnym typie projektu.

Zwróć uwagęInfragistics jest zarejestrowanym znakiem towarowym odpowiedniego właściciela. Ta strona nie jest powiązana, zatwierdzona ani sponsorowana przez Infragistics. Wszystkie nazwy produktów, logo i marki są własnością ich odpowiednich właścicieli. Porównania mają charakter wyłącznie informacyjny i odzwierciedlają informacje dostępne publicznie w momencie pisania.

Często Zadawane Pytania

Dlaczego warto przejść z Infragistics BarCode na IronBarcode?

Typowe powody to uproszczenie licencjonowania (eliminacja złożoności związanej z SDK i kluczem uruchomieniowym), zniesienie limitów przepustowości, uzyskanie natywnej obsługi plików PDF, usprawnienie wdrażania w środowisku Docker/CI/CD oraz ograniczenie powtarzalnego kodu API w kodzie produkcyjnym.

Jak zastąpić wywołania API Infragistics za pomocą IronBarcode?

Zastąp standardowe fragmenty kodu dotyczące tworzenia instancji i licencjonowania wyrażeniem IronBarCode.License.LicenseKey = "key". Zastąp wywołania czytnika wyrażeniem BarcodeReader.Read(path), a wywołania zapisu wyrażeniem BarcodeWriter.CreateBarcode(data, encoding). Metody statyczne nie wymagają zarządzania instancjami.

Jak bardzo zmienia się kod podczas migracji z Infragistics BarCode do IronBarcode?

Większość migracji skutkuje zmniejszeniem liczby linii kodu. Usuwane są standardowe fragmenty dotyczące licencji, konstruktory instancji oraz jawna konfiguracja formatów. Podstawowe operacje odczytu/zapisu są mapowane na krótsze odpowiedniki w IronBarcode z bardziej przejrzystymi obiektami wynikowymi.

Czy podczas migracji muszę mieć zainstalowane zarówno Infragistics BarCode, jak i IronBarcode?

Nie. Większość migracji polega na bezpośredniej wymianie, a nie na równoległym działaniu. Należy migrować po jednej klasie usługowej na raz, zastąpić odwołanie do NuGet oraz zaktualizować wzorce instancjonowania i wywoływania API przed przejściem do kolejnej klasy.

Jaka jest nazwa pakietu NuGet dla IronBarcode?

Pakiet nosi nazwę „IronBarcode” (z wielkimi literami B i C). Zainstaluj go za pomocą polecenia „Install-Package IronBarcode” lub „dotnet add package IronBarcode”. Dyrektywa using w kodzie to „using IronBarcode;”.

W jaki sposób IronBarcode upraszcza wdrażanie Docker w porównaniu z Infragistics BarCode?

IronBarcode to pakiet NuGet bez zewnętrznych plików SDK ani konfiguracji licencji. W Dockerze należy ustawić zmienną środowiskową IRONBARCODE_LICENSE_KEY, a pakiet zajmie się weryfikacją licencji podczas uruchamiania.

Czy IronBarcode automatycznie wykrywa wszystkie formaty kodów kreskowych po migracji z Infragistics?

Tak. IronBarcode automatycznie wykrywa symbole we wszystkich obsługiwanych formatach. Wyraźne wyliczenie typów kodów kreskowych nie jest wymagane. Jeśli format jest już znany, a wydajność ma znaczenie, BarcodeReaderOptions pozwala ograniczyć obszar wyszukiwania w celu optymalizacji.

Czy IronBarcode może odczytywać BarCodes z plików PDF bez oddzielnej biblioteki?

Tak. BarCodeReader.Read("document.pdf") przetwarza pliki PDF natywnie. Wyniki obejmują PageNumber, Format, Value i Confidence dla każdego znalezionego kodu kreskowego. Nie jest wymagany żaden zewnętrzny etap renderowania pliku PDF.

W jaki sposób IronBarcode obsługuje równoległe przetwarzanie kodów kreskowych?

Metody statyczne IronBarcode są bezstanowe i bezpieczne dla wątków. Użyj Parallel.ForEach bezpośrednio na listach plików bez zarządzania instancjami dla poszczególnych wątków. BarcodeReaderOptions.MaxParallelThreads kontroluje wewnętrzny limit wątków.

Jakie właściwości wyników ulegają zmianie podczas migracji z Infragistics BarCode do IronBarcode?

Typowe zmiany nazw: BarcodeValue staje się Value, BarcodeType staje się Format. Wyniki IronBarcode zawierają również Confidence i PageNumber. Funkcja wyszukiwania i zamiany w całym rozwiązaniu obsługuje zmiany nazw w istniejącym kodzie przetwarzania wyników.

Jak skonfigurować licencjonowanie IronBarcode w potoku CI/CD?

Zapisz IronBarcode_LICENSE_KEY jako sekret potoku i przypisz IronBarCode.License.LicenseKey w kodzie uruchamiającym aplikację. Jeden sekret obejmuje wszystkie środowiska, w tym środowisko programistyczne, testowe, przejściowe i produkcyjne.

Czy IronBarcode obsługuje generowanie kodów QR z niestandardowym stylem?

Tak. Funkcja QRCodeWriter.CreateQrCode() obsługuje niestandardowe kolory za pomocą ChangeBarCodeColor(), osadzanie logo za pomocą AddBrandLogo(), konfigurowalne poziomy korekcji błędów oraz wiele formatów wyjściowych, w tym PNG, JPG, PDF i strumień.

Curtis Chau
Autor tekstów technicznych

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podrę...

Czytaj więcej

Zespół wsparcia Iron

Jesteśmy online 24 godziny, 5 dni w tygodniu.
Czat
E-mail
Zadzwoń do mnie