iText.Commons.Utils.DIContainer.GetInstance[T] 在Android Unity中抛出空引用异常
我正在使用iText生成PDF。在编辑器(Windows)中运行正常,但在进行Android构建时,抛出以下异常:
2026/06/01 12:45:41.669 29785 29810错误Unity
NullReferenceException: 对象引用未设置到对象的实例。2026/06/01 12:45:41.669 29785 29810错误Unity
at iText.Commons.Utils.DIContainer.GetInstance[T] () [0x00000] in <00000000000000000000000000000000>:02026/06/01 12:45:41.669 29785 29810错误Unity
at iText.Kernel.Pdf.PdfPagesTree..ctor (iText.Kernel.Pdf.PdfCatalog pdfCatalog) [0x00000] in <00000000000000000000000000000000>:02026/06/01 12:45:41.669 29785 29810错误Unity
at iText.Kernel.Pdf.PdfCatalog..ctor (iText.Kernel.Pdf.PdfDictionary pdfObject) [0x00000] in <00000000000000000000000000000000>:02026/06/01 12:45:41.669 29785 29810错误Unity
at iText.Kernel.Pdf.PdfDocument.Open (iText.Kernel.Pdf.PdfVersion newPdfVersion) [0x00000] in <00000000000000000000000000000000>:02026/06/01 12:45:41.669 29785 29810错误Unity
at iText.Kernel.Pdf.PdfDocument..ctor (iText.Kernel.Pdf.PdfWriter writer) [0x00000] in <00000000000000000000000000000000>:02026/06/01 12:45:41.669 29785 29810错误Unity
at PdfGenerator.CreatePdfFromImages (System.Collections.Generic.List`1[T] imagePaths, System.String pdfFileName, System.String ouputPath) [0x00000] in <00000000000000000000000000000000>:02026/06/01 12:45:41.669 29785 29810错误Unity
以下是我部分的PDF生成代码。我可以确认 pdfdocument 日志没有出现:
Debug.Log("=====PDF GENERATION STARTED=====");
// 1. Initialize PDF writer and PDF document
PdfWriter writer = new PdfWriter(savePath);
Debug.Log("PDF Writer initialized at: " + savePath);
System.Runtime.CompilerServices.RuntimeHelpers
.RunClassConstructor(typeof(iText.Commons.Utils.DIContainer).TypeHandle);
Debug.Log("DIContainer cctor forced");
PdfDocument pdfDoc = new PdfDocument(writer);
Debug.Log("PDF Document created successfully.");
// 2. Initialize layout Document (Defaults to A4)
Document document = new Document(pdfDoc, PageSize.A4);
Debug.Log("Layout Document initialized with A4 page size.");
// 2. Instantiate your custom handler
HeaderFooterHandler handler = new HeaderFooterHandler();
以下是我的 link.xml 文件,以确保最终构建中不会排除任何代码。也许这会有问题?
<linker>
<!-- Force preservation of DIContainer AND its static constructor -->
<assembly fullname="itext.commons" preserve="all">
<type fullname="iText.Commons.Utils.DIContainer" preserve="all">
<method signature="Void .cctor()" />
</type>
<type fullname="iText.Commons.Utils.DIContainerConfigurations" preserve="all">
<method signature="Void .cctor()" />
<method signature="Microsoft.Extensions.DependencyInjection.IServiceProvider Build()" />
<method signature="Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(Microsoft.Extensions.DependencyInjection.IServiceCollection)" />
</type>
<type fullname="iText.Commons.Actions.ProductProcessorFactoryKeeper" preserve="all">
<method signature="Void .cctor()" />
</type>
<type fullname="iText.Commons.Actions.Processors.DefaultProductProcessorFactory" preserve="all">
<method signature="Void .cctor()" />
</type>
<type fullname="iText.Commons.Bouncycastle.BouncyCastleFactoryCreator" preserve="all">
<method signature="Void .cctor()" />
</type>
</assembly>
<assembly fullname="itext.kernel" preserve="all">
<type fullname="iText.Kernel.Pdf.PdfDocument" preserve="all">
<method signature="Void .cctor()" />
</type>
<type fullname="iText.Kernel.Pdf.PdfPagesTree" preserve="all">
<method signature="Void .cctor()" />
</type>
</assembly>
<!-- Keep everything else the same as before -->
<assembly fullname="itext" preserve="all"/>
<assembly fullname="itext.io" preserve="all"/>
<assembly fullname="itext.layout" preserve="all"/>
<assembly fullname="itext.bouncy-castle-adapter" preserve="all"/>
<assembly fullname="itext.bouncy-castle-fips-adapter" preserve="all"/>
<assembly fullname="BouncyCastle.Cryptography" preserve="all"/>
<assembly fullname="Microsoft.Extensions.DependencyInjection" preserve="all"/>
<assembly fullname="Microsoft.Extensions.DependencyInjection.Abstractions" preserve="all"/>
<assembly fullname="Microsoft.Extensions.Logging" preserve="all"/>
<assembly fullname="Microsoft.Extensions.Logging.Abstractions" preserve="all"/>
<assembly fullname="Microsoft.Extensions.Options" preserve="all"/>
<assembly fullname="Microsoft.Extensions.Primitives" preserve="all"/>
<assembly fullname="Microsoft.Bcl.AsyncInterfaces" preserve="all"/>
<assembly fullname="System.Text.Json" preserve="all"/>
<assembly fullname="System.Text.Encodings.Web" preserve="all"/>
<assembly fullname="System.Runtime.Loader" preserve="all"/>
<assembly fullname="System.Reflection.TypeExtensions" preserve="all"/>
</linker>
解决方案
你能指明你正在使用的版本吗?
另外,在Android部署方面你使用的是怎样的设置?如果你在使用AOT,可能需要告诉AOT哪些反射类会被使用。
你可能需要使用一个:ILLink.Descriptors.xml(将其放在项目根文件夹中,紧邻csproj文件)
<linker>
<assembly fullname="itext.font_asian" preserve="all" />
<assembly fullname="itext.hyph" preserve="all" />
<assembly fullname="itext.kernel">
<type fullname="iText.Kernel.Utils.RegisterDefaultDiContainer" preserve="all" />
</assembly>
<assembly fullname="itext.forms">
<type fullname="iText.Forms.Util.RegisterDefaultDiContainer" preserve="all" />
</assembly>
</linker>
你可以把它添加到你的 .csproj 中,如下所示:
一些示例csproj文件
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>aot_cli_sample</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="itext" Version="9.7.0-SNAPSHOT" />
<PackageReference Include="itext.commons" Version="9.7.0-SNAPSHOT" />
<PackageReference Include="itext.font-asian" Version="9.7.0-SNAPSHOT" />
<PackageReference Include="itext.hyph" Version="9.7.0-SNAPSHOT" />
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.7.0-SNAPSHOT" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ILLink.Descriptors.xml">
<LogicalName>ILLink.Descriptors.xml</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Project>
如果那样不起作用(应该会起作用),你也可以尝试手动添加依赖。
DocumentProperties documentProperties = new DocumentProperties();
documentProperties.RegisterDependency(typeof(IPageTreeListFactory), new DefaultPageTreeListFactory(50000));
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream()), documentProperties);
但请注意,这并不是唯一会被自动注册的依赖,因此ILink的 XML文件是更好的选择,否则你可能还需要再添加其他一些内容。