跨平台和原生应用
Xamarin 和 .NET Native 等工具让 .NET 代码能够编译到特定平台。然而,由于 .NET 反射不一定在所有原生平台上 “正常工作” ,并且参数绑定和对象构造很大程度上依赖于反射,因此有时需要额外的工作才能使 Autofac 和依赖注入(DI)正常工作。
Xamarin
使用 Xamarin 创建 iOS 或 Android 应用时,如果启用了链接器,可能需要明确指定需要反射支持的类型。Xamarin 自定义链接器配置 文档解释了如何通知链接器保留某些类型,而不会从最终产品中移除它们。具体来说...
- 使用
[Preserve]
属性标记您拥有的类型 - 在构建过程中包含自定义 XML 链接描述文件
一个简单的链接描述文件如下所示:
<linker>
<assembly fullname="mscorlib">
<type fullname="System.Convert" />
</assembly>
<assembly fullname="My.Own.Assembly">
<type fullname="Foo" preserve="fields">
<method name=".ctor" />
</type>
<namespace fullname="My.Own.Namespace" />
<type fullname="My.Other*" />
</assembly>
<assembly fullname="Autofac" preserve="all"/>
</linker>
Autofac 在 lambda 表达式中使用 System.Convert.ChangeType
方法进行类型转换,因此需要将其包含在链接器定义中。有关进一步讨论,请参阅 issue #842。
关于如何组织 Xamarin 自定义链接器配置文件以及如何将其包含在构建中,可以查看 Xamarin 文档。
Xamarin 链接器可能不会认为 Autofac 是“链接器安全”的。如果链接器过于激进,可能会看到类似以下异常:
The type 'Autofac.Features.Indexed.KeyedServiceIndex'2' does not implement the interface 'Autofac.Features.Indexed.IIndex'2'
[此 StackOverflow 回答](https://stackoverflow.com/questions/58114288/autofac-build-throws-exception-on-latest-xamarin-ios-when-linker-configured-to) 指出可以采取以下措施之一:
- 将链接器设置为
Don't link
或Link Framework SDKs Only
(这将增加应用程序大小) - 在 iOS 项目的属性中,在“iOS Build”下的“Additional mtouch arguments”中添加
--linkskip=Autofac
参数。 - 使用上述链接器 XML,并确保包含
preserve="all"
的Autofac
行。
.NET Native
.NET Native 是一种将 .NET 可执行文件编译为原生代码的方法。它用于 Universal Windows 平台 (UWP) 和 Windows 商店应用等场景。
当使用 .NET Native 进行反射 时,如果编译器删除了您需要的类型的反射元数据,可能会遇到 MissingMetadataException
等异常。
您可以使用 运行时指令 (rd.xml) 文件 来配置 .NET Native 编译。一个简单的指令文件如下所示:
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="*Application*" Dynamic="Required All" />
</Application>
</Directives>
该指令文件告诉编译器保留整个应用程序包中所有内容的所有反射数据。这是一种“核选项”——如果您想减小应用程序包的大小,可以更具体地指定要包括的内容。有关更多详细信息,请参考 MSDN 文档。