C# Conditional Attribute:如何处理平台专属using指令?
问题描述
我正在开发一款C#跨平台应用,目前用条件编译来导入平台专属的Firebase插件:
#if IOS using Plugin.Firebase.iOS; #else using Plugin.Firebase.Android; #endif
业务代码里也用#if分支调用平台专属方法:
void SomeMethod(Events events) { #if IOS events.AddiOS(_ => { // AddiOS仅在iOS插件版本中存在 // iOS专属逻辑 }); #else events.AddAndroid(_ => { // AddAndroid仅在Android插件版本中存在 // Android专属逻辑 }); #endif }
最近尝试用[Conditional("IOS")]重构平台专属代码到独立方法时遇到了问题:如果保留原来的条件using,编译器会找不到Plugin.Firebase.iOS;如果移除using的#if判断,又会因为引用了不存在的平台包而编译失败。想知道有没有办法把using指令和Conditional方法关联起来?补充:当条件方法不依赖需要通过#if导入的包时,Conditional Attribute可以正常工作。
可行的解决方法
1. 用条件编译包裹条件方法的完整定义
既然平台专属命名空间仅在对应平台下存在,可将整个条件方法的定义(包括用到的平台类型)用#if包裹,同时保留原有的条件using:
#if IOS using Plugin.Firebase.iOS; #else using Plugin.Firebase.Android; #endif void SomeMethod(Events events) { AddPlatformSpecificHandler(events); } #if IOS [Conditional("IOS")] void AddPlatformSpecificHandler(Events events) { events.AddiOS(_ => { // iOS专属逻辑 }); } #else [Conditional("ANDROID")] void AddPlatformSpecificHandler(Events events) { events.AddAndroid(_ => { // Android专属逻辑 }); } #endif
编译器在对应平台编译时,只会处理当前平台的方法定义和命名空间引用,不会出现找不到类型的问题。
2. 使用C# 10+的全局条件别名(推荐)
如果项目使用C# 10或更高版本,可通过全局条件别名统一平台类型的引用,减少重复的#if分支:
首先在项目全局文件(如GlobalUsings.cs)中定义条件别名:
#if IOS global using FirebasePlatform = Plugin.Firebase.iOS; #else global using FirebasePlatform = Plugin.Firebase.Android; #endif
然后在业务代码中用统一别名引用平台类型,结合Conditional Attribute:
void SomeMethod(Events events) { AddPlatformHandler(events); } [Conditional("IOS")] void AddPlatformHandler(Events events) { events.AddiOS(_ => { // iOS逻辑 }); } [Conditional("ANDROID")] void AddPlatformHandler(Events events) { events.AddAndroid(_ => { // Android逻辑 }); }
注意:AddiOS和AddAndroid仍是平台专属方法,需确保对应条件方法仅在目标平台编译时生效;也可进一步抽象接口,让平台项目实现后通过依赖注入获取实例,彻底摆脱条件编译。
3. 拆分平台专属代码到独立文件
将iOS和Android的专属代码分别放到不同文件中,通过项目文件的条件编译控制文件的包含:
创建PlatformHandlers.iOS.cs:
using Plugin.Firebase.iOS; [Conditional("IOS")] public static void AddPlatformHandler(Events events) { events.AddiOS(_ => { // iOS逻辑 }); }
创建PlatformHandlers.Android.cs:
using Plugin.Firebase.Android; [Conditional("ANDROID")] public static void AddPlatformHandler(Events events) { events.AddAndroid(_ => { // Android逻辑 }); }
在项目的.csproj文件中添加:
<ItemGroup> <Compile Include="PlatformHandlers.iOS.cs" Condition="'$(TargetFramework)' == 'net7.0-ios'" /> <Compile Include="PlatformHandlers.Android.cs" Condition="'$(TargetFramework)' == 'net7.0-android'" /> </ItemGroup>
每个平台编译时只会包含对应文件,不会出现命名空间找不到的问题,业务代码可直接调用AddPlatformHandler无需写#if分支。
内容的提问来源于stack exchange,提问作者Adam B

