如何使用 IoC 构造函数注入 (MvvmCross (MvvmCross.Platform.Exceptions.MvxIoCResolveException))
How To Use IoC Constructor Injection (MvvmCross (MvvmCross.Platform.Exceptions.MvxIoCResolveException))
所以我对 MVVM(MvvmCross)/Android 还是个新手。如果我做的事情真的很愚蠢,请道歉。
我一直在 "MvxGeoLocation" 和 "IMvxMessenger" 上关注 Stuart Lodge 的 N=9 视频,我确信我一直在关注它,但我不知道我在哪里'我出错了。
但是我的应用程序无法从构造函数解析接口。
App.cs:
public override void Initialize()
{
CreatableTypes()
.EndingWith("Service")
.AsInterfaces()
.RegisterAsLazySingleton();
RegisterAppStart<ViewModels.MainViewModel>();
}
MainViewModel.cs:
public MainViewModel(ILocationService locationService, IMvxMessenger messenger)
{
_subscriptionToken = messenger.Subscribe<LocationMessage>(OnLocationMessage);
}
LocationService.cs:
Public class LocationService : ILocationService
{
private readonly MvxLocationWatcher _locationWatcher;
private readonly IMvxMessenger _messenger;
public LocationService(MvxLocationWatcher locationWatcher, IMvxMessenger messenger)
{
_locationWatcher = locationWatcher;
_messenger = messenger;
if (!_locationWatcher.Started) _locationWatcher.Start(new MvxLocationOptions(), OnLocation, OnError);
}
private void OnLocation(MvxGeoLocation location)
{
System.Diagnostics.Debug.WriteLine(location.Coordinates.Longitude.ToString(), location.Coordinates.Latitude);
var message = new LocationMessage(this, location.Coordinates.Longitude, location.Coordinates.Latitude);
_messenger.Publish(message);
}
public void CustomLocation(double lng, double lat)
{
var message = new LocationMessage(this, lng, lat);
_messenger.Publish(message);
}
private void OnError(MvxLocationError error)
{
Mvx.Error(error.Code.ToString());
}
}
public class LocationMessage : MvxMessage
{
public LocationMessage(object sender, double lng, double lat) : base(sender)
{
Lng = lng;
Lat = lat;
}
public double Lng { get; private set; }
public double Lat { get; private set; }
}
现在 ILocationService 接口是空的。出于国际奥委会的原因,它就在那里。现在,当我 运行 应用程序时,它在 "base.OnCreate(bundle);" 上的 MainView Activity 上崩溃。
现在在重写 InitializeIoC 方法中我什至不能 "Mvx.RegisterSingleton(new LocationService());" 因为我需要给出我显然不能给出的参数。我什至尝试使用 "Mvx.IocConstruct();",但我意识到这行不通,因为 MvvmCross 会自动执行此操作。
所以报错信息:
Failed to construct and initialize ViewModel for type Core.ViewModels.MainViewModel from locator MvxDefaultViewModelLocator - check InnerException for more information
InnerException:
{MvvmCross.Platform.Exceptions.MvxException: Problem creating viewModel of type MainViewModel ---> MvvmCross.Platform.Exceptions.MvxIoCResolveException: Failed to resolve parameter for parameter locationService of type ILocationService when creating Core.ViewModels.MainViewModel
at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.GetIoCParameterValues (System.Type type, System.Reflection.ConstructorInfo firstConstructor) [0x00036] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\IoC\MvxSimpleIoCContainer.cs:502
at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.IoCConstruct (System.Type type) [0x0002c] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\IoC\MvxSimpleIoCContainer.cs:312
at MvvmCross.Platform.Mvx.IocConstruct (System.Type t) [0x00006] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\Mvx.cs:169
at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00000] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxDefaultViewModelLocator.cs:33
--- End of inner exception stack trace ---
at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x0000f] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxDefaultViewModelLocator.cs:37
at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState, MvvmCross.Core.ViewModels.IMvxViewModelLocator viewModelLocator) [0x0000e] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:69 }
如果需要可以提供 StackTrace。
那么我究竟做错了什么?我花了很多时间试图弄清楚这一点。没头绪。
更新:
添加 StackTrace(以防有帮助):
" at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState, MvvmCross.Core.ViewModels.IMvxViewModelLocator viewModelLocator) [0x00020] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:73 \n at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00020] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:59 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.ViewModelFromRequest (MvvmCross.Core.ViewModels.MvxViewModelRequest viewModelRequest, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00006] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:104 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.CreateViewModelFromIntent (Android.Content.Intent intent, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00029] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:98 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.Load (Android.Content.Intent intent, MvvmCross.Core.ViewModels.IMvxBundle savedState, System.Type viewModelTypeHint) [0x00089] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:67 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions.LoadViewModel (MvvmCross.Droid.Views.IMvxAndroidView androidView, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00065] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityViewExtensions.cs:137 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions+<>c__DisplayClass1_0.b__1 () [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityViewExtensions.cs:50 \n at MvvmCross.Core.Views.MvxViewExtensionMethods.OnViewCreate (MvvmCross.Core.Views.IMvxView view, System.Func1[TResult] viewModelLoader) [0x00012] in C:\projects\mvvmcross\MvvmCross\Core\Core\Views\MvxViewExtensionMethods.cs:28 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions.OnViewCreate (MvvmCross.Droid.Views.IMvxAndroidView androidView, Android.OS.Bundle bundle) [0x00068] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityViewExtensions.cs:50 \n at MvvmCross.Droid.Views.MvxActivityAdapter.EventSourceOnCreateCalled (System.Object sender, MvvmCross.Platform.Core.MvxValueEventArgs
1[T] eventArgs) [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityAdapter.cs:80 \n at (wrapper delegate-invoke) System.EventHandler1[MvvmCross.Platform.Core.MvxValueEventArgs
1[Android.OS.Bundle]]:invoke_void_object_TEventArgs (object,MvvmCross.Platform.Core.MvxValueEventArgs1<Android.OS.Bundle>)\n at MvvmCross.Platform.Core.MvxDelegateExtensionMethods.Raise[T] (System.EventHandler
1[TEventArgs] eventHandler, System.Object sender, T value) [0x00000] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\Core\MvxDelegateExtensionMethods.cs:21 \n at MvvmCross.Platform.Droid.Views.MvxEventSourceActivity.OnCreate (Android.OS.Bundle bundle) [0x00014] in C:\projects\mvvmcross\MvvmCross\Platform\Droid\Views\MvxEventSourceActivity.cs:34 \n at MvvmCross.Droid.Views.MvxActivity.OnCreate (Android.OS.Bundle bundle) [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivity.cs:92 \n at Droid.Views.MainView.OnCreate (Android.OS.Bundle bundle) [0x00001] in /Users/jaydeephasmukhlal/Projects/LocationMessengerTest/Droid/Views/MainView.cs:13 \n at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x0000f] in :0 \n at (wrapper dynamic-method) System.Object:e63afbc8-7ae5-4091-981d-084af38f92fc (intptr,intptr,intptr)"
您正在 LocationService
构造函数 MvxLocationWatcher
中使用具体类型。这应该是 IMvxLocationWatcher
,然后 IoC 将根据平台为您注入具体的 class(请记住还要在所有平台上安装位置插件)。您可以查看 MvvmCross Location Plugin docs 了解更多信息。
切换这个:
public LocationService(MvxLocationWatcher locationWatcher, IMvxMessenger messenger)
对此:
public LocationService(IMvxLocationWatcher watcher, IMvxMessenger messenger)
好吧,我终于得到了前辈的帮助,发现了我犯的愚蠢错误。我的界面 class ILocationService
实际上是 class 而不是界面。
示例 ILocationService 是:
public class ILocationService
{
}
而不是:
public interface ILocationService
{
}
因此,将 class 更改为接口解决了问题。这就是它无法初始化 ILocationService 的原因。
所以我对 MVVM(MvvmCross)/Android 还是个新手。如果我做的事情真的很愚蠢,请道歉。
我一直在 "MvxGeoLocation" 和 "IMvxMessenger" 上关注 Stuart Lodge 的 N=9 视频,我确信我一直在关注它,但我不知道我在哪里'我出错了。
但是我的应用程序无法从构造函数解析接口。
App.cs:
public override void Initialize()
{
CreatableTypes()
.EndingWith("Service")
.AsInterfaces()
.RegisterAsLazySingleton();
RegisterAppStart<ViewModels.MainViewModel>();
}
MainViewModel.cs:
public MainViewModel(ILocationService locationService, IMvxMessenger messenger)
{
_subscriptionToken = messenger.Subscribe<LocationMessage>(OnLocationMessage);
}
LocationService.cs:
Public class LocationService : ILocationService
{
private readonly MvxLocationWatcher _locationWatcher;
private readonly IMvxMessenger _messenger;
public LocationService(MvxLocationWatcher locationWatcher, IMvxMessenger messenger)
{
_locationWatcher = locationWatcher;
_messenger = messenger;
if (!_locationWatcher.Started) _locationWatcher.Start(new MvxLocationOptions(), OnLocation, OnError);
}
private void OnLocation(MvxGeoLocation location)
{
System.Diagnostics.Debug.WriteLine(location.Coordinates.Longitude.ToString(), location.Coordinates.Latitude);
var message = new LocationMessage(this, location.Coordinates.Longitude, location.Coordinates.Latitude);
_messenger.Publish(message);
}
public void CustomLocation(double lng, double lat)
{
var message = new LocationMessage(this, lng, lat);
_messenger.Publish(message);
}
private void OnError(MvxLocationError error)
{
Mvx.Error(error.Code.ToString());
}
}
public class LocationMessage : MvxMessage
{
public LocationMessage(object sender, double lng, double lat) : base(sender)
{
Lng = lng;
Lat = lat;
}
public double Lng { get; private set; }
public double Lat { get; private set; }
}
现在 ILocationService 接口是空的。出于国际奥委会的原因,它就在那里。现在,当我 运行 应用程序时,它在 "base.OnCreate(bundle);" 上的 MainView Activity 上崩溃。
现在在重写 InitializeIoC 方法中我什至不能 "Mvx.RegisterSingleton(new LocationService());" 因为我需要给出我显然不能给出的参数。我什至尝试使用 "Mvx.IocConstruct();",但我意识到这行不通,因为 MvvmCross 会自动执行此操作。
所以报错信息:
Failed to construct and initialize ViewModel for type Core.ViewModels.MainViewModel from locator MvxDefaultViewModelLocator - check InnerException for more information
InnerException:
{MvvmCross.Platform.Exceptions.MvxException: Problem creating viewModel of type MainViewModel ---> MvvmCross.Platform.Exceptions.MvxIoCResolveException: Failed to resolve parameter for parameter locationService of type ILocationService when creating Core.ViewModels.MainViewModel at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.GetIoCParameterValues (System.Type type, System.Reflection.ConstructorInfo firstConstructor) [0x00036] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\IoC\MvxSimpleIoCContainer.cs:502 at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.IoCConstruct (System.Type type) [0x0002c] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\IoC\MvxSimpleIoCContainer.cs:312 at MvvmCross.Platform.Mvx.IocConstruct (System.Type t) [0x00006] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\Mvx.cs:169 at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00000] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxDefaultViewModelLocator.cs:33 --- End of inner exception stack trace --- at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x0000f] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxDefaultViewModelLocator.cs:37 at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState, MvvmCross.Core.ViewModels.IMvxViewModelLocator viewModelLocator) [0x0000e] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:69 }
如果需要可以提供 StackTrace。 那么我究竟做错了什么?我花了很多时间试图弄清楚这一点。没头绪。
更新:
添加 StackTrace(以防有帮助):
" at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState, MvvmCross.Core.ViewModels.IMvxViewModelLocator viewModelLocator) [0x00020] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:73 \n at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00020] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:59 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.ViewModelFromRequest (MvvmCross.Core.ViewModels.MvxViewModelRequest viewModelRequest, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00006] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:104 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.CreateViewModelFromIntent (Android.Content.Intent intent, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00029] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:98 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.Load (Android.Content.Intent intent, MvvmCross.Core.ViewModels.IMvxBundle savedState, System.Type viewModelTypeHint) [0x00089] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:67 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions.LoadViewModel (MvvmCross.Droid.Views.IMvxAndroidView androidView, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00065] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityViewExtensions.cs:137 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions+<>c__DisplayClass1_0.b__1 () [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityViewExtensions.cs:50 \n at MvvmCross.Core.Views.MvxViewExtensionMethods.OnViewCreate (MvvmCross.Core.Views.IMvxView view, System.Func
1[TResult] viewModelLoader) [0x00012] in C:\projects\mvvmcross\MvvmCross\Core\Core\Views\MvxViewExtensionMethods.cs:28 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions.OnViewCreate (MvvmCross.Droid.Views.IMvxAndroidView androidView, Android.OS.Bundle bundle) [0x00068] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityViewExtensions.cs:50 \n at MvvmCross.Droid.Views.MvxActivityAdapter.EventSourceOnCreateCalled (System.Object sender, MvvmCross.Platform.Core.MvxValueEventArgs
1[T] eventArgs) [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityAdapter.cs:80 \n at (wrapper delegate-invoke) System.EventHandler1[MvvmCross.Platform.Core.MvxValueEventArgs
1[Android.OS.Bundle]]:invoke_void_object_TEventArgs (object,MvvmCross.Platform.Core.MvxValueEventArgs1<Android.OS.Bundle>)\n at MvvmCross.Platform.Core.MvxDelegateExtensionMethods.Raise[T] (System.EventHandler
1[TEventArgs] eventHandler, System.Object sender, T value) [0x00000] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\Core\MvxDelegateExtensionMethods.cs:21 \n at MvvmCross.Platform.Droid.Views.MvxEventSourceActivity.OnCreate (Android.OS.Bundle bundle) [0x00014] in C:\projects\mvvmcross\MvvmCross\Platform\Droid\Views\MvxEventSourceActivity.cs:34 \n at MvvmCross.Droid.Views.MvxActivity.OnCreate (Android.OS.Bundle bundle) [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivity.cs:92 \n at Droid.Views.MainView.OnCreate (Android.OS.Bundle bundle) [0x00001] in /Users/jaydeephasmukhlal/Projects/LocationMessengerTest/Droid/Views/MainView.cs:13 \n at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x0000f] in :0 \n at (wrapper dynamic-method) System.Object:e63afbc8-7ae5-4091-981d-084af38f92fc (intptr,intptr,intptr)"
您正在 LocationService
构造函数 MvxLocationWatcher
中使用具体类型。这应该是 IMvxLocationWatcher
,然后 IoC 将根据平台为您注入具体的 class(请记住还要在所有平台上安装位置插件)。您可以查看 MvvmCross Location Plugin docs 了解更多信息。
切换这个:
public LocationService(MvxLocationWatcher locationWatcher, IMvxMessenger messenger)
对此:
public LocationService(IMvxLocationWatcher watcher, IMvxMessenger messenger)
好吧,我终于得到了前辈的帮助,发现了我犯的愚蠢错误。我的界面 class ILocationService
实际上是 class 而不是界面。
示例 ILocationService 是:
public class ILocationService
{
}
而不是:
public interface ILocationService
{
}
因此,将 class 更改为接口解决了问题。这就是它无法初始化 ILocationService 的原因。