跳至頁尾內容
開發者更新

Moq C#(開發者的工作原理)

在軟體開發的世界中,測試是一個不可或缺的過程。 它確保您的程式碼運行如預期,並在進入生產環節之前幫助捕捉錯誤。 測試中一個重要的方面是模擬,而在C#測試中,MOQ是開發者工具箱中的強大工具。 它提供對lambda表達式的支持。 MOQ,全名為"Mock Object Framework for .NET",簡化了為單元測試建立模擬物件的過程。 在本文中,我們將深入研究C#中的MOQ。

什麼是MOQ?

MOQ - Mocking Framework for .NET 是一個.NET應用程式的模擬框架,允許開發者快速有效地建立模擬物件。 模擬對像模擬應用程式中實際物件的行為,使得隔離和測試程式碼的特定部分變得更容易。 MOQ簡化了建立和使用這些模擬物件的過程。

MOQ的主要特點

  • 流暢介面: MOQ提供了一個流暢且富有表現力的API,用於設定期望和驗證。 這使您的測試程式碼更易讀且更易於理解。
  • 強型別: MOQ利用C#語言特性來提供強型別和IntelliSense支持,當定義模擬和期望時。 這減少了測試中的運行時錯誤的可能性。
  • 鬆散模擬: MOQ支持既嚴格又鬆散的模擬。 鬆散模擬允許您建立模擬物件以響應任何方法調用,而嚴格模擬則強制僅調用預期的方法。
  • 可驗證行為: MOQ允許您驗證在模擬物件上調用了特定的方法且傳入的參數和順序正確。
  • 回調和返回: 您可以定義回調來在被模擬的方法調用時執行自訂程式碼,並為模擬的方法指定返回值。

開始使用MOQ

在本教程中,我們將探討如何使用MOQ這個C#的流行模擬框架來促進單元測試。 我們將演示一個範例,其中我們使用MOQ來模擬依賴來建立和測試一個簡單的ATM交易場景。

建立一個新的C#專案

按照以下步驟來建立一個新專案:

  1. 打開Visual Studio,進入"File">"New">"Project..."。
  2. 選擇一個專案模板,配置設定,然後點擊"Create"。

Moq C#(開發者如何運作)圖1 - 在Visual Studio 2022中建立一個新的控制臺應用程式

假設您正在為ATM(自動櫃員機)開發軟體,且需要測試身份認證和提款功能。 ATM依賴於兩個介面:IHostBankIHSMModule。 我們想要測試代表ATM提款功能的ATMCashWithdrawal類。

建立兩個介面,IHostBankIHSMModule,這代表ATM系統的依賴。 定義相關的方法如ValidatePIN

// IHostBank.cs
public interface IHostBank
{
    bool AuthenticateAmount(string accountNumber, int amount);
}

// IHSMModule.cs
public interface IHSMModule
{
    bool ValidatePIN(string cardNumber, int pin);
}
// IHostBank.cs
public interface IHostBank
{
    bool AuthenticateAmount(string accountNumber, int amount);
}

// IHSMModule.cs
public interface IHSMModule
{
    bool ValidatePIN(string cardNumber, int pin);
}
' IHostBank.cs
Public Interface IHostBank
	Function AuthenticateAmount(ByVal accountNumber As String, ByVal amount As Integer) As Boolean
End Interface

' IHSMModule.cs
Public Interface IHSMModule
	Function ValidatePIN(ByVal cardNumber As String, ByVal pin As Integer) As Boolean
End Interface
$vbLabelText   $csharpLabel

建立使用上述依賴來執行ATM操作的ATMCashWithdrawal類。 在這個類中,您將實施一個似WithdrawAmount的方法。

// ATMCashWithdrawal.cs
public class ATMCashWithdrawal
{
    private readonly IHSMModule hsmModule;
    private readonly IHostBank hostBank;

    public ATMCashWithdrawal(IHSMModule hsmModule, IHostBank hostBank)
    {
        this.hsmModule = hsmModule;
        this.hostBank = hostBank;
    }

    // Withdraw amount after validating PIN and balance
    public bool WithdrawAmount(string cardNumber, int pin, int amount)
    {
        if (!hsmModule.ValidatePIN(cardNumber, pin))
        {
            return false;
        }

        if (!hostBank.AuthenticateAmount(cardNumber, amount))
        {
            return false;
        }

        // Withdraw the specified amount and perform other operations
        return true;
    }
}
// ATMCashWithdrawal.cs
public class ATMCashWithdrawal
{
    private readonly IHSMModule hsmModule;
    private readonly IHostBank hostBank;

    public ATMCashWithdrawal(IHSMModule hsmModule, IHostBank hostBank)
    {
        this.hsmModule = hsmModule;
        this.hostBank = hostBank;
    }

    // Withdraw amount after validating PIN and balance
    public bool WithdrawAmount(string cardNumber, int pin, int amount)
    {
        if (!hsmModule.ValidatePIN(cardNumber, pin))
        {
            return false;
        }

        if (!hostBank.AuthenticateAmount(cardNumber, amount))
        {
            return false;
        }

        // Withdraw the specified amount and perform other operations
        return true;
    }
}
' ATMCashWithdrawal.cs
Public Class ATMCashWithdrawal
	Private ReadOnly hsmModule As IHSMModule
	Private ReadOnly hostBank As IHostBank

	Public Sub New(ByVal hsmModule As IHSMModule, ByVal hostBank As IHostBank)
		Me.hsmModule = hsmModule
		Me.hostBank = hostBank
	End Sub

	' Withdraw amount after validating PIN and balance
	Public Function WithdrawAmount(ByVal cardNumber As String, ByVal pin As Integer, ByVal amount As Integer) As Boolean
		If Not hsmModule.ValidatePIN(cardNumber, pin) Then
			Return False
		End If

		If Not hostBank.AuthenticateAmount(cardNumber, amount) Then
			Return False
		End If

		' Withdraw the specified amount and perform other operations
		Return True
	End Function
End Class
$vbLabelText   $csharpLabel

建立單元測試專案

現在,讓我們使用MOQ來模擬依賴並為ATMCashWithdrawal類建立單元測試。

在您的解決方案中建立一個新的單元測試專案並命名為ATMSystem.Tests

要將NUnit測試專案新增到您的Visual Studio解決方案中,請按照以下步驟操作:

  1. 右鍵點擊解決方案: 在"Solution Explorer"(通常在右側),右鍵點擊解決方案名稱。
  2. 新增 > 新專案: 從彈出選單中選擇"Add"然後選擇"New Project..."。
  3. 建立新專案: 在"Add New Project"對話框中,您可以搜索"NUnit"來找到可用的NUnit模板。 如下所示選擇NUnit Test Project。

Moq C#(開發者如何運作)圖2 - 在您的解決方案中新增一個新的NUnit Test Project。

  1. 配置專案: 根據需要配置專案設定,包括專案名稱和位置。
  2. 點擊OK: 點擊"Create"或"OK"按鈕將NUnit測試專案新增到您的解決方案中。

現在,您在解決方案中有一個單獨的NUnit測試專案,您可以在其中撰寫和管理您的單元測試。 您還可以加入對您想要測試的專案的引用,並在此專案中開始撰寫您的NUnit測試案例。

要在測試專案中開始使用MOQ,您需要將MOQ NuGet套件新增到您的解決方案中。 您可以使用Visual Studio中的NuGet Package Manager或在Package Manager Console中運行以下命令來完成此操作:

Install-Package Moq

此命令將安裝該套件並將所有必需的依賴加入到專案中。

使用NUnit和MOQ撰寫單元測試,以模擬ATMCashWithdrawal類。

using Moq;
using NUnit.Framework;

namespace ATMSystem.Tests
{
    public class ATMTests
    {
        private ATMCashWithdrawal atmCash;

        [SetUp]
        public void Setup()
        {
            // Arrange - Setup mock objects
            var hsmModuleMock = new Mock<IHSMModule>();
            hsmModuleMock.Setup(h => h.ValidatePIN("123456781234", 1234)).Returns(true);

            var hostBankMock = new Mock<IHostBank>();
            hostBankMock.Setup(h => h.AuthenticateAmount("123456781234", 500)).Returns(true);

            atmCash = new ATMCashWithdrawal(hsmModuleMock.Object, hostBankMock.Object);
        }

        [Test]
        public void WithdrawAmount_ValidTransaction_ReturnsTrue()
        {
            // Act - Execute the method under test
            bool result = atmCash.WithdrawAmount("123456781234", 1234, 500);

            // Assert - Verify the result
            Assert.IsTrue(result);
        }

        // More test cases for different scenarios (e.g., invalid PIN, insufficient funds)
    }
}
using Moq;
using NUnit.Framework;

namespace ATMSystem.Tests
{
    public class ATMTests
    {
        private ATMCashWithdrawal atmCash;

        [SetUp]
        public void Setup()
        {
            // Arrange - Setup mock objects
            var hsmModuleMock = new Mock<IHSMModule>();
            hsmModuleMock.Setup(h => h.ValidatePIN("123456781234", 1234)).Returns(true);

            var hostBankMock = new Mock<IHostBank>();
            hostBankMock.Setup(h => h.AuthenticateAmount("123456781234", 500)).Returns(true);

            atmCash = new ATMCashWithdrawal(hsmModuleMock.Object, hostBankMock.Object);
        }

        [Test]
        public void WithdrawAmount_ValidTransaction_ReturnsTrue()
        {
            // Act - Execute the method under test
            bool result = atmCash.WithdrawAmount("123456781234", 1234, 500);

            // Assert - Verify the result
            Assert.IsTrue(result);
        }

        // More test cases for different scenarios (e.g., invalid PIN, insufficient funds)
    }
}
Imports Moq
Imports NUnit.Framework

Namespace ATMSystem.Tests
	Public Class ATMTests
		Private atmCash As ATMCashWithdrawal

		<SetUp>
		Public Sub Setup()
			' Arrange - Setup mock objects
			Dim hsmModuleMock = New Mock(Of IHSMModule)()
			hsmModuleMock.Setup(Function(h) h.ValidatePIN("123456781234", 1234)).Returns(True)

			Dim hostBankMock = New Mock(Of IHostBank)()
			hostBankMock.Setup(Function(h) h.AuthenticateAmount("123456781234", 500)).Returns(True)

			atmCash = New ATMCashWithdrawal(hsmModuleMock.Object, hostBankMock.Object)
		End Sub

		<Test>
		Public Sub WithdrawAmount_ValidTransaction_ReturnsTrue()
			' Act - Execute the method under test
			Dim result As Boolean = atmCash.WithdrawAmount("123456781234", 1234, 500)

			' Assert - Verify the result
			Assert.IsTrue(result)
		End Sub

		' More test cases for different scenarios (e.g., invalid PIN, insufficient funds)
	End Class
End Namespace
$vbLabelText   $csharpLabel

在此測試程式碼中,我們正在使用MOQ為IHostBank建立模擬物件,並在測試期間調用時指定它們的行為。

在上述程式碼範例中,我們演示了在C#中使用MOQ模擬物件的概念。 我們為IHostBank介面建立模擬物件,模擬它們在單元測試中的行為。 這使得我們可以通過控制這些模擬物件的回應,將ATMCashWithdrawal類隔離並徹底測試。 通過模擬,我們可以確保我們的程式碼正確地與這些依賴交互,使我們的測試集中、可預測,並能有效地識別特定程式碼單元中的問題。 此做法增強了整體可靠性、可維護性和測試程式碼質量。

步驟3:運行測試

  1. 建立您的解決方案以確保一切都是最新的。
  2. 在Visual Studio中打開"Test Explorer"(Test > Test Explorer)。
  3. 在Test Explorer中點擊"Run All"按鈕來執行您的單元測試。
  4. 查看測試結果。 您應該看到您撰寫的測試(WithdrawAmount_ValidTransaction_ReturnsTrue)通過。

Moq C#(開發者如何運作)圖3 - 要運行測試,您首先需要建立解決方案。 成功建立後,在Visual Studio中打開Test Explorer,然後點擊Run All按鈕開始執行您的單元測試。

通過這種方式,我們可以隔離我們想要測試的程式碼並確保它在不同情況下的行為符合預期,通過有效地模擬依賴。 這種做法提高了軟體的可靠性和可維護性,使得在開發過程早期識別和修復問題更加容易。

介紹 IronPDF

IronPDF Documentation and Features Overview 是一個強大的C#程式庫,允許開發者在其應用程式中處理PDF文件。 它提供廣泛的功能,包括從各種來源(如HTML、圖像和現有PDF)建立、修改和轉換PDF文件。 與之前教程中討論的模擬物件概念結合使用,IronPDF可以成為在單元測試中生成和操作PDF文件的寶貴工具。

IronPDF的主要功能是其HTML到PDF轉換功能,確保版面和樣式的完整性。 它將網頁內容轉換成PDF,使其非常適合用於報告、發票和文件。 此功能支持將HTML文件、URL和HTML字串轉換為PDF。

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim renderer = New ChromePdfRenderer()

		' 1. Convert HTML String to PDF
		Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
		Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
		pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")

		' 2. Convert HTML File to PDF
		Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
		Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
		pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")

		' 3. Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
$vbLabelText   $csharpLabel

例如,如果您有一個涉及PDF生成或處理的專案,您可以使用IronPDF來建立模擬PDF文件來模擬真實世界場景。 這對於測試和驗證您的程式碼如何與PDF文件交互特別有用。 您可以生成具有特定內容、布局和屬性的模擬PDF,然後使用它們作為測試夾具,以確保您的程式碼生成所需的PDF輸出或正確處理PDF相關操作。

生成PDF的模擬物件

假設您正在開發一個生成財務報告的應用程式,這些報告需要保存並以PDF格式分發。 在此場景中,您可能想要測試PDF生成並確保內容和格式正確。

首先,我們需要將IronPDF加入到我們的專案中。 在NuGet套件管理器控制台中撰寫以下命令來安裝IronPDF。

Install-Package IronPdf

此命令將安裝並新增必要的依賴到我們的專案中。

以下是如何將IronPDF整合到單元測試過程中的說明:

生成模擬PDF

您可以使用IronPDF建立具有特定內容和樣式的模擬PDF文件來模擬真實的財務報告。 這些模擬PDF可以作為您的單元測試的測試夾具,如以下程式碼片段所示:

public class PDFGenerator
{
    public void GenerateFinancialReport(string reportData)
    {
        var renderer = new ChromePdfRenderer();

        // Generate the report HTML
        string reportHtml = GenerateReportHtml(reportData);
        PdfDocument pdfDocument = renderer.RenderHtmlAsPdf(reportHtml);

        // Save the PDF to a file or memory stream
        pdfDocument.SaveAs("FinancialReport.pdf");
    }

    private string GenerateReportHtml(string reportData)
    {
        // Generate the report HTML based on the provided data
        // (e.g., using Razor views or any HTML templating mechanism)
        // Return the HTML as a string
        return "<h1>my Report</h1>";
    }
}
public class PDFGenerator
{
    public void GenerateFinancialReport(string reportData)
    {
        var renderer = new ChromePdfRenderer();

        // Generate the report HTML
        string reportHtml = GenerateReportHtml(reportData);
        PdfDocument pdfDocument = renderer.RenderHtmlAsPdf(reportHtml);

        // Save the PDF to a file or memory stream
        pdfDocument.SaveAs("FinancialReport.pdf");
    }

    private string GenerateReportHtml(string reportData)
    {
        // Generate the report HTML based on the provided data
        // (e.g., using Razor views or any HTML templating mechanism)
        // Return the HTML as a string
        return "<h1>my Report</h1>";
    }
}
Public Class PDFGenerator
	Public Sub GenerateFinancialReport(ByVal reportData As String)
		Dim renderer = New ChromePdfRenderer()

		' Generate the report HTML
		Dim reportHtml As String = GenerateReportHtml(reportData)
		Dim pdfDocument As PdfDocument = renderer.RenderHtmlAsPdf(reportHtml)

		' Save the PDF to a file or memory stream
		pdfDocument.SaveAs("FinancialReport.pdf")
	End Sub

	Private Function GenerateReportHtml(ByVal reportData As String) As String
		' Generate the report HTML based on the provided data
		' (e.g., using Razor views or any HTML templating mechanism)
		' Return the HTML as a string
		Return "<h1>my Report</h1>"
	End Function
End Class
$vbLabelText   $csharpLabel

使用模擬PDF進行單元測試

我們將撰寫使用IronPDF來生成代表各種報告場景的模擬PDF的測試。 然後,我們將我們的程式碼生成的實際PDF與這些模擬PDF進行比較,以確保內容、格式和結構如預期。

using IronPdf;
using NUnit.Framework;

internal class PDFGeneratorTests
{
    [Test]
    public void GenerateFinancialReport_CreatesCorrectPDF()
    {
        // Arrange
        var pdfGenerator = new PDFGenerator();
        var expectedPdf = PdfDocument.FromFile("ExpectedFinancialReport.pdf"); // Load a mock PDF

        // Act
        pdfGenerator.GenerateFinancialReport("Sample report data");
        var actualPdf = PdfDocument.FromFile("FinancialReport.pdf");

        // Assert
        Assert.AreEqual(actualPdf.ExtractAllText(), expectedPdf.ExtractAllText());
    }
}
using IronPdf;
using NUnit.Framework;

internal class PDFGeneratorTests
{
    [Test]
    public void GenerateFinancialReport_CreatesCorrectPDF()
    {
        // Arrange
        var pdfGenerator = new PDFGenerator();
        var expectedPdf = PdfDocument.FromFile("ExpectedFinancialReport.pdf"); // Load a mock PDF

        // Act
        pdfGenerator.GenerateFinancialReport("Sample report data");
        var actualPdf = PdfDocument.FromFile("FinancialReport.pdf");

        // Assert
        Assert.AreEqual(actualPdf.ExtractAllText(), expectedPdf.ExtractAllText());
    }
}
Imports IronPdf
Imports NUnit.Framework

Friend Class PDFGeneratorTests
	<Test>
	Public Sub GenerateFinancialReport_CreatesCorrectPDF()
		' Arrange
		Dim pdfGenerator As New PDFGenerator()
		Dim expectedPdf = PdfDocument.FromFile("ExpectedFinancialReport.pdf") ' Load a mock PDF

		' Act
		pdfGenerator.GenerateFinancialReport("Sample report data")
		Dim actualPdf = PdfDocument.FromFile("FinancialReport.pdf")

		' Assert
		Assert.AreEqual(actualPdf.ExtractAllText(), expectedPdf.ExtractAllText())
	End Sub
End Class
$vbLabelText   $csharpLabel

在此測試程式碼中,我們生成了一個代表預期輸出的模擬PDF(actualPdf)進行比較。 我們已提取兩個PDF的內容以驗證它們是否擁有相同的內容。

結論

總而言之,將MOQ與IronPDF結合到我們的單元測試過程中,讓我們能夠全面核實我們的軟體應用程式的行為。 MOQ使我們能夠隔離特定程式碼組件,控制依賴並模擬複雜的場景,使我們能撰寫專注和可靠的測試。

同時,IronPDF通過促進PDF文件的生成和操作,增強了我們的測試能力,確保我們的PDF相關功能得到徹底檢驗。 通過將這些工具整合到我們的測試工具包中,我們可以自信地開發出符合功能和效能要求的強大高質量軟體。 這種與MOQ單元測試和IronPDF PDF驗證相結合的大大提高了我們應用程式的整體質量和可靠性。

值得注意的是,IronPDF提供了免費試用以測試其功能。 如果您發現它符合您的需求,您可以選擇購買商業授權,這允許您繼續使用IronPDF的功能在您的專案中,享受授權版本的全部優勢和支持,確保PDF相關功能的平穩整合到您的應用程式中。

常見問題

Moq如何增強C#中的單元測試?

Moq通過允許開發者建立模擬物件來增強C#中的單元測試,這些模擬物件可以模擬真實物件的行為。這有助於孤立開發者希望測試的特定程式碼組件,確保更準確和有針對性的測試結果。

Moq的主要功能是什麼?

Moq提供流暢的接口設置預期,強型別以減少運行時錯誤,並支持嚴格和寬鬆模擬,這使其成為C#應用程式中單元測試的有效工具。

如何將IronPDF整合到C#專案中以生成PDF?

要將IronPDF整合到C#專案中,您可以使用NuGet套件管理器控制台並運行命令Install-Package IronPdf。這將新增生成和操作PDF所需的依賴項到您的應用程式中。

在單元測試中使用模擬PDF的目的何在?

模擬PDF用於單元測試中,以模擬涉及PDF文件的真實情境。這允許開發者測試PDF生成和操作功能,確保他們的應用程式能夠正確處理PDF。

IronPDF可以用於商業應用嗎?

可以,IronPDF提供商業授權選項,允許開發者在商業應用中使用其完整的PDF功能,並享有授權版本提供的支援和功能。

如何在單元測試中同時使用Moq和IronPDF?

Moq可用於模擬程式碼中的依賴項,而IronPDF可用於生成和操作PDF。它們的結合允許開發者編寫可靠的測試,確保程式碼邏輯和PDF相關功能的質量。

Moq在測試C#中的依賴關係互動中扮演什麼角色?

Moq通過允許開發者建立介面的模擬實現,比如`IHostBank`和`IHSMModule`,來幫助測試依賴關係的互動。這讓您可以模擬各種情境,並核實您的程式碼是否按預期與依賴項互動。

Moq如何處理嚴格和寬鬆模擬?

Moq支持嚴格和寬鬆模擬。嚴格模擬要求滿足所有預期,這對於精確測試非常有用。寬鬆模擬更靈活,只需驗證感興趣的互動,這在複雜系統中會很有幫助。

Jacob Mellor,首席技術官 @ Team Iron
首席技術官

Jacob Mellor是Iron Software的首席技術官,一位在C# PDF技術上開創先河的遠見工程師。作為Iron Software核心程式碼庫的原開發者,他從創立以來就一直在塑造公司的產品架構,與首席執行官Cameron Rimington一起將公司轉變為服務於NASA、特斯拉和全球政府公司的50多名人員的公司。

Jacob擁有曼徹斯特大學的土木工程一等榮譽學士學位(BEng),於1998-2001年之間獲得。在1999年於倫敦創辦他的第一家軟體公司並於2005年建立了他的第一批.NET元組件後,他專注於解決Microsoft生態系統中的複雜問題。

他的旗艦IronPDF和Iron Suite .NET程式庫在全球獲得了超過3000萬次NuGet安裝依據,他的基礎程式碼基繼續支援著世界各地開發者使用的工具。擁有25年的商業經驗和41年的程式設計專業知識,他仍專注於推動企業級C#、Java和Python PDF技術的創新,同時指導下一代技術領導者。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話