2013-06-25 4 views
1

que je suis avec le tutoriel sur YouTube pour N=2: Kittens and ListsMvvmCross IoC incapable de résoudre le service

Le KittenView souffle quand il frappe OnCreate()

Cirrious.CrossCore.Exceptions.MvxException: Échec de charge ViewModel pour le type MyApp.Core.ViewModels.KittenViewModel de localisateur MvxDefaultViewModelLocator

il semble qu'il ne soit pas en mesure de résoudre le service (IKittenGenesisService), car lorsque j'ajoute un constructeur vide, l'application s'exécute sans erreur. Mais évidemment, la vue ne fonctionnera pas correctement sans ses dépendances.

La même solution a également un tutoriel plus tôt, qui comprend le FirstViewModel, qui utilise un ICalculationService. Ce service résout bien et s'exécute, donc je sais que le MVVM IoC fonctionne. Mais je ne peux pas trouver de différences entre les deux. Cela ne m'aide pas que je ne puisse pas déboguer dans un projet PCL, mais c'est un problème différent.

public class App: MvxApplication 
{ 
    public override void Initialize() 
    { 
     CreatableTypes() 
      .EndingWith("Service") 
      .AsInterfaces() 
      .RegisterAsLazySingleton(); 
     RegisterAppStart<KittenViewModel>(); 
    } 
} 

[Activity(Label = "View for KittenViewModel")] 
public class KittenView : MvxActivity 
{ 
    protected override void OnCreate(Bundle bundle) 
    { 
     base.OnCreate(bundle); 
     SetContentView(Resource.Layout.KittenView); 
    } 
} 

public class KittenViewModel: MvxViewModel 
{ 
    public KittenViewModel(IKittenGenesisService service) 
    { 
     var kittenList = new List<Kitten>(); 
     for (var i = 0; i < 100; i++) 
     { 
      var newKitten = service.CreateNewKitten(i.ToString()); 
      kittenList.Add(newKitten); 
     } 
     Kittens = kittenList; 
    } 

    private List<Kitten> _kittens; 
    public List<Kitten> Kittens 
    { 
     get { return _kittens; } 
     set 
     { 
      _kittens = value; 
      RaisePropertyChanged(() => Kittens); 
     } 
    } 
} 

public class KittenGenesisService: IKittenGenesisService 
{ 
    private readonly List<string> _names; 
    private readonly Random _random; 

    public KittenGenesisService() 
    { 
     _random = new Random(); 
     _names = new List<string>() 
     { 
      "Tiddles", 
      "Amazon", 
      "Pepsi", 
      "Solomon", 
      "Butler", 
      "Snoopy", 
      "Harry", 
      "Holly", 
      "Paws" 
     }; 
    } 

    public Kitten CreateNewKitten(string extra = "") 
    { 
     return new Kitten() 
      { 
       Name = _names[Random(_names.Count)] + extra, 
       ImageUrl = string.Format("http://placekitten.com/{0}/{0}"), 
       Price = RandomPrice() 
      }; 
    } 

    public int Random(int count) 
    { 
     return _random.Next(count); 
    } 

    public int RandomPrice() 
    { 
     return Random(23) + 3; 
    } 
} 

Pourtant, ces fonctionnent très bien:

[Activity(Label = "View for FirstViewModel")] 
public class FirstView : MvxActivity 
{ 
    protected override void OnCreate(Bundle bundle) 
    { 
     base.OnCreate(bundle); 
     SetContentView(Resource.Layout.FirstView); 
    } 
} 

public class FirstViewModel: MvxViewModel 
{ 
    private readonly ICalculationService _calculationService; 

    public FirstViewModel(ICalculationService calculationService) 
    { 
     _calculationService = calculationService; 
     _generosity = 20; 
     _subTotal = 100; 
     Recalc(); 
    } 
    // more code 
} 

Voici un test unitaire j'ajouté, il souffle immédiatement avec une exception de référence null quand il essaie de nouveau un KittenViewModel, le constructeur KittenGenesisService est appelé bien.

[TestFixture] 
public class KittenViewModelTests 
{ 
    private KittenViewModel _sut; 

    [SetUp] 
    public void given_a_kittenviewmodel() 
    { 
     _sut = new KittenViewModel(new KittenGenesisService()); 
    } 

    [Test] 
    public void the_view_model_contains_kittens() 
    { 
     _sut.Kittens.Should().NotBeEmpty(); 
    } 
} 

Répondre

3

Je pense qu'il pourrait être utile de vérifier si certains les bases comme:

  • est là une classe publique qui met en œuvre le service de genèse?
  • a-t-il un constructeur public sans paramètre? (Ou un constructeur qui pourrait lui-même être construit)

Si ces choses sont ok, alors il est probablement intéressant d'essayer quelques techniques de débogage:

  • permettant la trace afin que vous puissiez voir les détails internes des problèmes - voir MvvmCross Mvx.Trace usage
  • expérimenter avec un code de test dans votre app.cs - après que les services ont été enregistrés, Mvx.CanResolve<IKittenGenesisService>() est-il vrai?
  • en essayant d'appeler votre code de modèle de vue à partir d'un test unitaire - est-ce que cela fonctionne?
+0

Merci pour les conseils. J'ai ajouté mon code KittenGenesisService ainsi qu'un test unitaire. Il explose en essayant d'appeler le constructeur KittenViewModel. –

+1

Si vraiment "exploser" alors s'il vous plaît poster une vidéo - comme je voudrais regarder. Si à la place, il lance simplement une exception, alors vérifiez le message d'erreur d'exception et la ligne à partir de laquelle il se trouve - car cela peut vous dire ce qui ne va pas ... je suppose que ce sera une exception FormatException string.Format ("http://placekitten.com/{0}/{0}") ' – Stuart

+0

Ne pensez pas que cela pointe vers le problème, j'ai un test unitaire similaire pour FirstViewModel et il lance une exception dans le même endroit. Quelque chose sous les couvertures avec mvvm ne me laisse pas un nouveau viewmodel pour les tests unitaires. –

Questions connexes