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
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
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;Imports IronBarCodeKrok 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";Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"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);Imports Infragistics.Win.UltraWinBarcode
Dim barcode As New UltraWinBarcode()
barcode.Symbology = Symbology.Code128
barcode.Data = "ITEM-12345"
barcode.SaveTo(outputPath)Po (IronBarcode):
// 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)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);Imports IronBarCode
BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128) _
.ResizeTo(400, 100) _
.SaveAsPng(outputPath)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;
}
}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 SubPo (IronBarcode — 2 wiersze):
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")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}");
}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 Ifresult.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})");
}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})")
NextBrak 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");
}
}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 ClassBarcodeReader.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})");
}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})")
NextInfragistics 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();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()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;
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)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(Of InfragisticsBarcodeService)() ' implements IDisposable
' After: no registration needed — use static method directly, or wrap in thin service if preferred
' services.AddScoped(Of IBarcodeService, IronBarcodeService)()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();
}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 ClassBrak 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);Imports IronBarCode
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = False
}
Dim results = BarcodeReader.Read(imagePath, options)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"))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";netJeś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";
});
}Option Strict On
Option Infer 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 FunctionZmiany 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" .
Przejrzyj wszystkie dopasowania:
- Zamiany
UltraWinBarcode: zamień naBarcodeWriter.CreateBarcode() - Bloki
new BarcodeReader()+DecodeComplete: zamień naBarcodeReader.Read() - Listy flag
SymbologyType: usuń całkowicie - Ładowania
BitmapImageużywane dla danych wejściowych z kodami kreskowymi: zamień na bezpośrednią ścieżkę/strumień/bajty - Ciało wywołań zwrotnych
ReaderDecodeArgs e: wyodrębnije.Value→result.Value,e.Symbology→result.Format IDisposablew 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.

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ęczników.