从Infragistics条形码迁移到IronBarcode
大多数Infragistics条形码迁移都是因为团队需要在只能生成条形码的项目中读取条形码(WinForms、 ASP.NET Core或 WPF 以外的任何项目),或者因为事件驱动的 WPF 读取器 API 被证明对生产环境来说太脆弱。 桥接模式SymbologyType标志所导致的静默失败,都是团队寻找替代方案的常见原因。
本指南将逐步完成整个迁移过程:移除Infragistics条形码包,替换 WinForms 和 WPF 上下文中的生成和读取代码,并将条形码功能添加到Infragistics完全不支持的项目类型中。
快速入门
步骤 1:移除Infragistics条形码包
从项目中移除Infragistics条形码NuGet包。 根据您使用的目标类型而定:
# WinForms generation package
dotnet remove package Infragistics.WinForms.Barcode
# WPF reading package
dotnet remove package Infragistics.WPF.BarcodeReader
如果你的项目文件同时引用了这两个文件,请将它们都删除。 如果您正在使用其他Infragistics组件,则移除条形码特定软件包不会影响InfragisticsUltimate 许可证。
步骤 2:安装IronBarcode
dotnet add package IronBarcode
IronBarcode是一个可在 WinForms、WPF、 ASP.NET Core、控制台、 Blazor Server、Docker、Azure Functions 和 AWS Lambda 上运行的单一软件包。 每个框架不需要单独的软件包。
步骤 3:更新命名空间
将Infragistics条形码命名空间替换为IronBarCode(大写B,大写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 IronBarCode步骤 4:初始化许可证
在应用程序启动时添加一次许可证初始化——App.xaml.cs,或者您的DI组合根:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"代码迁移示例
WinForms 生成:UltraWinBarcode 到 BarcodeWriter
WinForms生成模式能够与IronBarcode的BarcodeWriter很好地对应:
之前(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)(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)Infragistics的CreateBarcode()的一个参数,而不是属性赋值。 数据成为首要论据。 .SaveAsPdf()。
如果您需要在保存前调整条形码大小:
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)WPF 事件驱动读取:从服务类到两行代码
这是移民数量减少幅度最大的一次。InfragisticsWPF 读取模式需要一个完整的服务类:
修改前(Infragistics WPF — 约 35 行代码):
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(IronBarcode — 2 行之后):
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")整个服务类——实例管理、事件布线、Dispose()——都消失了。 BarcodeReader.Read()是同步的、静态的,并直接接受文件路径字符串。
如果您还要返回符号类型:
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 Ife.Value。 e.Symbology。
添加 WinForms 读取功能(以前不可能实现)
如果您之前在 WinForms 项目中只进行了生成操作,现在可以使用同一个包进行读取操作了:
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无需额外的软件包,无需特定的框架设置。同样的BarcodeReader.Read()调用在WinForms和WPF中都有效。
ASP.NET Core端点(以前不可能实现)
使用Infragistics包无法在ASP.NET Core控制器中生成和读取条形码。 使用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 ClassStream——无需先将上传保存到磁盘。
PDF条形码读取
IronBarcode可以直接从 PDF 文档中读取条形码——无需单独的软件包:
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 没有类似的解决方案——PDF 条形码读取需要先将 PDF 页面转换为图像,然后再进行扫描。
批处理:从顺序到并行
之前(Infragistics——顺序执行,不具备并行化所需的并发安全性):
// 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()(IronBarcode并行、线程安全)之后:
using IronBarCode;
// Option 1: pass an array directly —IronBarcodehandles 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)移除处置模式
如果您的代码在InfragisticsIDisposable实现,这些可以完全删除。 IronBarcode的BarcodeReader是一个静态类。 没有实例需要创建,没有事件处理程序需要分离,也没有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)()用于依赖注入的轻量级包装服务非常简单:
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没有构造函数注入,没有Dispose(),没有事件管理。
常见迁移问题
符号类型标志已移除
Infragistics WPF读取器上的SymbologyTypes属性要求您列举想要支持的每种条形码格式。 IronBarcode没有同类产品——每次读取时都会自动检测所有 50 多种受支持的格式。
这有一个重要的副作用:如果特定的条形码格式因为其SymbologyType标志缺失而之前静默失败,IronBarcode现在能找到它。 您可能会在生产过程中看到以前被悄悄吞掉的条形码值出现。 这是正确的做法——这些条形码一直都在那里。
如果需要限制返回的格式(出于性能或歧义原因),BarcodeReaderOptions支持这一点:
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)无需加载位图图像
Infragistics WPF读取器需要通过BitmapSource对象。 IronBarcode直接接受文件路径字符串、字节数组和数据流:
// 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"))您可以删除任何仅用于与条形码相关的图像加载的using System.Windows.Media.Imaging;导入。
TaskCompletionSource 模式已移除
连接事件驱动的TaskCompletionSource<string>字段已完全消失。 BarcodeReader.Read()是同步的并直接返回结果。
如果您的调用代码是await service.ReadBarcodeAsync(path),可以简化为:
// Before
var value = await service.ReadBarcodeAsync(imagePath);
// After
var value = BarcodeReader.Read(imagePath).FirstOrDefault()?.Value ?? "No barcode found";net如果您想为下游调用者保留异步接口,同时又不阻塞线程:
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 Function物业名称变更
| Infragistics | IronBarcode |
|---|---|
ReaderDecodeArgs中) | result.Value |
ReaderDecodeArgs中) | result.Format |
barcode.Data | BarcodeWriter.CreateBarcode()的第一个参数 |
barcode.Symbology = Symbology.Code128 | BarcodeEncoding.Code128(参数) |
barcode.SaveTo(path) | .SaveAsPng(path) / .SaveAsJpeg(path) / .SaveAsSvg(path) |
迁移清单
使用以下 grep 模式查找代码库中所有Infragistics条形码的使用情况:
# 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" .
逐场比赛进行分析:
UltraWinBarcode用法: 替换为BarcodeWriter.CreateBarcode()new BarcodeReader()+BarcodeReader.Read()SymbologyType标志列表: 完全删除- 用于条形码输入的
BitmapImage加载:替换为直接路径/流/字节 ReaderDecodeArgs e回调体: 提取e.Value→result.Value,e.Symbology→result.Format- 在条形码服务类上的
_reader,则移除
功能对比
| 特征 | Infragistics条形码 | IronBarcode |
|---|---|---|
| WinForms条形码生成 | 是的(UltraWinBarcode) | 是 |
| WinForms条形码读取 | 不可用 | 是 |
| WPF 条形码生成 | 是的(XamBarcode) | 是 |
| WPF 条形码读取 | 是的(事件驱动型) | 是的(同步) |
| ASP.NET Core | 不可用 | 是 |
| 控制台/工作服务 | 不可用 | 是 |
| Docker / Linux | 不可用 | 是 |
| Azure Functions | 不可用 | 是 |
| Blazor服务器 | 不可用 | 是 |
| 自动格式检测 | 否——需要符号学类型标志 | 是 |
| PDF条形码读取 | 不可用 | 是的(母语) |
| 线程安全的并发读取 | 否 | 是 |
| 批量读取(内置) | 否 | 是 |
| QR码纠错控制 | 不可用 | 是 |
| 静态 API(无实例) | 否 | 是 |
| 需要Suite订阅 | 是(Infragistics Ultimate,$2,399+/年) | 否 |
| 永久许可证 | 否 | 是的——起价 749 美元 |
迁移后的主要好处
WinForms中的条形码读取。 如果迁移是由WinForms读取需求驱动的,这是主要结果:BarcodeReader.Read(imagePath)在WinForms中编译并运行,无需额外设置。
ASP.NET Core和控制台支持。Web API、后台服务和控制台工具现在都可以使用同一个包来生成和读取条形码。 如果您之前为这些项目类型维护了单独的工具链或变通方案,那么它们现在都不复存在了。
没有事件处理程序模板。 Dispose()清理都已移除。 剩下的只有条形码逻辑了。
没有符号规范。 由于缺少SymbologyType标志而之前静默失败的格式现在将被正确检测到。 自动检测功能无需配置即可覆盖所有 50 多种格式。
在所有项目类型中使用相同的服务类。 使用BarcodeService包装器可以跨WinForms、WPF、ASP.NET Core和解决方案中的任何其他项目共享。 没有特定于框架的实现。
**仅使用条形码功能无需订阅InfragisticsUltimate。**如果条形码支持是您项目订阅InfragisticsUltimate 的唯一原因,或者它是您做出决定的重要因素,那么IronBarcode是一个独立的软件包,提供永久授权选项,单开发者起价为 749 美元。
一旦找到所有Infragistics条形码的使用情况,迁移本身就是机械式的。 最复杂的部分是WPF服务类的替换,即便如此,也只是将类删除并用BarcodeReader.Read()替换调用。 版本迁移是一对一的属性/方法重命名。 您将获得一个单一、一致的 API,它适用于您需要的每种项目类型。

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。