Xamarin跨平台MVVM项目中单例模式失效问题及解决咨询
Xamarin单例实例重复创建问题排查与解决
初始解决方案结构
📦 Solution ┣ 📂 Main application ┃ ┣ 📂 ViewModel Project ┃ ┃ ┣ 📜 ... ┃ ┣ 📂 Android Project ┃ ┃ ┣ 📜 MyActivity.cs ┃ ┃ ┣ 📜 ... ┃ ┣ 📂 iOS Project ┃ ┃ ┣ 📜 ... ┗ 📂 Multiplaftorm Library ┣ 📂 Android-specific Library Project ┃ ┣ 📜 MyModuleAndroid.cs ┃ ┣ 📜 ... ┣ 📂 iOS-specific Library Project ┃ ┣ 📜 MyModuleiOS.cs ┃ ┣ 📜 ... ┣ 📂 Shared Library Project (.shproj) ┃ ┣ 📜 MyLibrary.Shared.projitems ┃ ┣ 📜 Service.cs ┃ ┣ 📜 Factory.cs ┃ ┣ 📜 IMyModule.cs ┃ ┣ 📜 ...
平台初始化相关代码
Android端初始化代码(MyActivity.cs)
[Activity(Label = "", WindowSoftInputMode = SoftInput.AdjustPan)] public class MyActivity { protected override void OnCreate(Bundle savedInstanceState) { MyModuleAndroid.Init(this); // 需要传入Activity实例 } // ... 其他代码 }
Android模块初始化逻辑(MyModuleAndroid.cs)
public class MyModuleAndroid { public static void Init(Activity activity) { Factory.GetInstance().DoSomething(); } }
单例工厂类(Factory.cs)
public class Factory { private static Factory instance; public static Factory GetInstance() { if (instance == null) { // 仅当实例不存在时创建新实例 instance = new Factory(); // 原代码中NFCModuleFactory推测为笔误 } return instance; } // ... 其他方法如DoSomething() }
问题现象
模块在Android端初始化完成后,首次通过Shared项目中的Service访问Factory实例时,发现instance为空,单例会被重新创建,导致之前初始化的数据全部丢失。调试确认GetInstance()被调用两次,new Factory()执行了两次——一次是在MyModuleAndroid的Init方法中,另一次是在Service的调用中。
临时解决方案
将Factory、IMyModule等类移至单独的标准类库项目(.csproj),调整后的多平台库结构如下:
┗ 📂 Multiplaftorm Library ┣ 📂 Android-specific Library Project ┃ ┣ 📜 MyModuleAndroid.cs ┃ ┣ 📜 ... ┣ 📂 iOS-specific Library Project ┃ ┣ 📜 MyModuleiOS.cs ┃ ┣ 📜 ... ┣ 📂 Shared Library Project (.shproj) ┃ ┣ 📜 MyLibrary.Shared.projitems ┃ ┣ 📜 Service.cs ┣ 📂 Standard Project (.csproj) ┃ ┣ 📜 Factory.cs ┃ ┣ 📜 IMyModule.cs ┃ ┣ 📜 ...
调整后单例实例可以保持全局唯一,初始化数据不再丢失。
问题根源
Xamarin的Shared Project(.shproj)并非真正的独立程序集,它的代码会被直接嵌入到所有引用它的项目中编译:
- Android项目引用该Shared Project时,Factory类会被编译到Android项目的程序集里
- ViewModel/Shared项目引用该Shared Project时,Factory类又会被编译到另一个程序集里
这两个程序集里的Factory类是完全独立的,各自拥有自己的静态instance字段,自然会出现两个不同的单例实例。
而标准的Class Library(.csproj)会被编译成一个独立的程序集,所有引用它的项目都会共享这个程序集中的类型和静态字段,因此Factory的静态instance字段是全局唯一的,单例逻辑可以正常工作。
内容的提问来源于stack exchange,提问作者Scare
相关产品推荐
相关产品推荐

