thi*_*ber 3 .net dependency-injection maui
我正在编写一个 .NET MAUI 应用程序,我想在我的 ViewModel 中使用Microsoft.Maui.Storage.Preferences,但是不希望将我的 ViewModel 绑定到静态Preferences类,否则将很难测试。所以我注意到有一个IPreferences接口,但我不知道它的目的是什么,因为我无法注入静态实现(并且首选项是静态的)。
在我的启动课程中,我做了通常的builder.Services.AddSingleton()事情.AddTransient():
builder.Services
.AddSingleton<AppShell>()
.AddTransient<MyViewModel>()
...
Run Code Online (Sandbox Code Playgroud)
但我不能用静态类来做到这一点。这是行不通的,因为你不能使用静态类作为类型参数:
.AddSingleton<IPreferences, Preferences>()
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为框架不提供它:
.AddSingleton<IPreferences>()
Run Code Online (Sandbox Code Playgroud)
我试着变得更奇特:
.AddSingleton<IPreferences>(_ => Preferences.Default)
Run Code Online (Sandbox Code Playgroud)
但我在使用它时收到此错误:
_preferences.Get("SomeKey", DateTime.Now); // error here, but _preferences is defined
Run Code Online (Sandbox Code Playgroud)
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object.
[mono-rt] at Microsoft.Maui.Storage.PreferencesImplementation.Get[DateTime](String key, DateTime defaultValue, String sharedName) in D:\a\_work\1\s\src\Essentials\src\Preferences\Preferences.android.cs:line 141
[mono-rt] at ... my filenames removed ... in ...\Shells\AppShell.xaml.cs:line 51
[mono-rt] at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
[mono-rt] at Android.App.SyncContext.<>c__DisplayClass2_0.<Post>b__0() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.App/SyncContext.cs:line 36
[mono-rt] at Java.Lang.Thread.RunnableImplementor.Run() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Java.Lang/Thread.cs:line 36
[mono-rt] at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net6.0/android-31/mcw/Java.Lang.IRunnable.cs:line 84
[mono-rt] at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 22
Run Code Online (Sandbox Code Playgroud)
我可以注入 IPreferences 还是必须创建由静态首选项支持的自己的接口?
IPreferences 用于保存小型键值对。您可以引用 Preferences.Default 来注入它。
然后使用:
settings.Get("Language", 0);
Run Code Online (Sandbox Code Playgroud)
其中设置是:
IPreferences settings;
Run Code Online (Sandbox Code Playgroud)
我喜欢做的是制作 SettingsService,然后使用:
public int Language
{
get => settings.Get("Language", 0);
set => settings.Set("Language", value);
}
Run Code Online (Sandbox Code Playgroud)
还有其他方法可以处理您的设置,但对于很少的值,这对我有用。
编辑(您请求的代码。)
注射:
builder.Services.AddSingleton<ISettings>(new SettingsService(Preferences.Default));
Run Code Online (Sandbox Code Playgroud)
I设置界面:
public interface ISettings
{
int Language { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
设置服务类:
internal class SettingsService : ISettings
{
IPreferences settings;
public SettingsService(IPreferences settings)
{
this.settings = settings;
}
public int Language
{
get => settings.Get("Language", 0);
set => settings.Set("Language", value);
}
}
Run Code Online (Sandbox Code Playgroud)
在 ViewModel 中使用:
public MyViewModel(ISettings settings)
{
lang = settings.Language;
}
Run Code Online (Sandbox Code Playgroud)
Edit2:因为你不想“手动构建”。你可以这样做。
builder.Services.AddSingleton<IPreferences>(Preferences.Default);
builder.Services.AddSingleton<ISettings, SettingsService>();
Run Code Online (Sandbox Code Playgroud)
这样您就可以使用 IPreferences 以及 ISettings。SettingsService 构造函数将使用此处注入的 IPreferences。
| 归档时间: |
|
| 查看次数: |
1369 次 |
| 最近记录: |