8 votes

Ninject - Binding.GetProvider lance NullReferenceException

Je suis en train d'utiliser la version 2.2.0.0 de Ninject dans une application web asp.net et après quelques centaines de requêtes, il lance parfois une NullReferenceException dans la méthode GetProvider de la classe Binding.

Exemple de stack trace : http://pastebin.com/BbhsPQMT

L'exception survient uniquement lorsque je teste l'application en stress et l'origine de l'exception est généralement différente (résolution d'interfaces distinctes).

Pour essayer de comprendre pourquoi ce problème se produisait, j'ai regardé le code source de Ninject et inséré quelques lignes de code à des fins de débogage. J'ai ensuite confirmé que l'objet qui est nul est la propriété ProviderCallback de la classe Binding.

J'ai également ajouté du code dans l'opérateur de définition de la propriété ProviderCallback afin de comprendre s'il était défini sur null. Après avoir effectué quelques tests et examiné quelques vidages de mémoire, il semble que la propriété ProviderCallback ne soit pas définie sur une valeur nulle et je pense que l'instance est collectée par GC.

Je ne comprends toujours pas pourquoi cela se produit...

Toute aide est grandement appréciée.

Éditer : Nous avons mis à jour la dernière version de Ninject juste pour vérifier si l'exception se produit toujours, mais nous avons obtenu la même exception après avoir testé l'application en stress : http://pastebin.com/YaiaZndz

2voto

Remo Gloor Points 26195

Je ne peux pas vous donner la raison de ce problème car je ne peux pas reproduire un tel comportement. Mais voici quelques étapes que vous pouvez suivre pour identifier le problème.

Comme vous le dites, le problème est causé par un ProviderCallback qui est null. Cela ne peut pas être causé par GC car GC ne assignera jamais null à une propriété. Au lieu de cela, vous obtiendrez une exception déjà disposée ou d'autres comportements étranges. Mais il y a d'autres raisons pour cela peut se produire :

  1. Null est assigné à un moment donné, mais comme vous l'avez déjà vérifié, ce n'est pas la raison.
  2. Il n'a jamais été assigné du tout.
  3. Une nouvelle BindingConfiguration est créée ultérieurement.

Le 3ème point peut facilement être vérifié en ajoutant un point d'arrêt dans le constructeur de BindingConfiguration. Il ne devrait plus être appelé une fois que le kernel est configuré avec succès et que vous commencez à résoudre les objets.

Pour le deuxième problème, exécutez ce qui suit après la configuration du kernel :

var kernel = votre kernel entièrement configuré;
var bindingsField = typeof(KernelBase).GetField("bindings", BindingFlags.NonPublic | BindingFlags.Instance);
var bindings = bindingsField.GetValue(kernel) as IEnumerable>>;

foreach (var bindingsEntry in bindings
    .Where(bindingsEntry => bindingsEntry.Value
        .Any(binding => binding.BindingConfiguration.ProviderCallback == null)))
{
    throw new Exception(string.Format("Aucun rappel de fournisseur défini pour {0}.", bindingsEntry.Key));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X