mercredi 20 juillet 2022

Singleton pattern doesn't work in Xamarin multi-platform project MVVM

I have a C# (Xamarin) solution structured like this:

📦 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
   ┃ ┣ 📜 ...

The module requires very device specific initialization, that I must do in the platform specific part (I make the example with Android)

// MyActivity.cs

[Activity(Label = "", WindowSoftInputMode = SoftInput.AdjustPan]
public class MyActivity
{   
    protected override void OnCreate(Bundle savedInstanceState)
    {
        MyModuleAndroid.Init(this); // I need an Activity as input
    }

...

The Init involves a singleton pattern:

// 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)
        {
            // only if no instance existing, I create a new one
            instance = new NFCModuleFactory();
        }

        return instance;
    }
...
}

Then, the instance is used inside the Service (shared project) that is called always from view model. But... here is the problem: the first time I try to access the instance (the second, after the initialization), I found it's null, so the singleton re-creates a new instance! If I call again from service the instance is mantained, but I already lost all my initalization data.

How can I solve this?

As a workaround, I noticed that If I structure my library like this, so by creating a fourth project that manages the factory (so the singleton), it works perfectly:

 ┗ 📂 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
   ┃ ┣ 📜 ...

As I said, in this way it works... but I really cannot understand why! :-(

Aucun commentaire:

Enregistrer un commentaire