9
votes

Ninject avec unité3D

Unity3D utilise GameObjects. Vous ajoutez des composants à ces gamebjects, où un composant est un script (en C # ou JS) qui hérite d'une classe de base. L'unité elle-même est écrite dans un code natif. Les composants ne peuvent pas avoir un constructeur et utilisent plutôt la réflexion pour trouver si vous avez certaines méthodes nommées (Onstart, mise à jour, etc.).

Au lieu de faire saigner mes yeux avec un manque de constructeurs et d'autres choses vraiment gênantes, j'ai pensé Je pourrais faire ce qui suit: p> xxx pré>

(monobehaviour est la classe de base) p> xxx pré>

.. alors je pourrais saisir GameObject .Transform ou qu'avez-vous de quelquegamebehaviour, tout en le découlant de l'unité exécutée retardée. P>

Le problème: Je ne pouvais pas utiliser le comportement d'injection par défaut car les composants / monobéhaviours ne peuvent pas avoir des constructeurs - il jette des erreurs à vous si vous essayez, alors j'ai roulé mon propre fournisseur. P>

NullReferenceException: Object reference not set to an instance of an object
Ninject.Infrastructure.Language.ExtensionsForMemberInfo.GetParentDefinition (System.Reflection.MethodInfo method, BindingFlags flags)
Ninject.Infrastructure.Language.ExtensionsForMemberInfo.GetParentDefinition (System.Reflection.PropertyInfo property)
Ninject.Infrastructure.Language.ExtensionsForMemberInfo.IsDefined (System.Reflection.PropertyInfo element, System.Type attributeType, Boolean inherit)
Ninject.Infrastructure.Language.ExtensionsForMemberInfo.HasAttribute (System.Reflection.MemberInfo member, System.Type type)
Ninject.Selection.Heuristics.StandardInjectionHeuristic.ShouldInject (System.Reflection.MemberInfo member)
Ninject.Selection.Selector+<>c__DisplayClass3.<SelectPropertiesForInjection>b__2 (IInjectionHeuristic h)
System.Linq.Enumerable.Any[IInjectionHeuristic] (IEnumerable`1 source, System.Func`2 predicate)
Ninject.Selection.Selector.<SelectPropertiesForInjection>b__1 (System.Reflection.PropertyInfo p)
System.Linq.Enumerable+<CreateWhereIterator>c__Iterator1D`1[System.Reflection.PropertyInfo].MoveNext ()
System.Collections.Generic.List`1[System.Reflection.PropertyInfo].AddEnumerable (IEnumerable`1 enumerable)
System.Collections.Generic.List`1[System.Reflection.PropertyInfo].AddRange (IEnumerable`1 collection)
Ninject.Selection.Selector.SelectPropertiesForInjection (System.Type type)
Ninject.Planning.Strategies.PropertyReflectionStrategy.Execute (IPlan plan)
Ninject.Planning.Planner+<>c__DisplayClass2.<GetPlan>b__0 (IPlanningStrategy s)
Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[IPlanningStrategy] (IEnumerable`1 series, System.Action`1 action)
Ninject.Planning.Planner.GetPlan (System.Type type)
Ninject.Activation.Context.Resolve ()
Ninject.KernelBase.<Resolve>b__4 (IContext context)
System.Linq.Enumerable+<CreateSelectIterator>c__Iterator10`2[Ninject.Activation.IContext,System.Object].MoveNext ()
System.Linq.Enumerable.Single[Object] (IEnumerable`1 source, System.Func`2 predicate, Fallback fallback)
System.Linq.Enumerable.SingleOrDefault[Object] (IEnumerable`1 source)
Ninject.Planning.Targets.Target`1[T].GetValue (System.Type service, IContext parent)
Ninject.Planning.Targets.Target`1[T].ResolveWithin (IContext parent)
Ninject.Activation.Providers.StandardProvider.GetValue (IContext context, ITarget target)
Ninject.Activation.Providers.StandardProvider+<>c__DisplayClass2.<Create>b__1 (ITarget target)
System.Linq.Enumerable+<CreateSelectIterator>c__Iterator10`2[Ninject.Planning.Targets.ITarget,System.Object].MoveNext ()
System.Collections.Generic.List`1[System.Object].AddEnumerable (IEnumerable`1 enumerable)
System.Collections.Generic.List`1[System.Object]..ctor (IEnumerable`1 collection)
System.Linq.Enumerable.ToArray[Object] (IEnumerable`1 source)
Ninject.Activation.Providers.StandardProvider.Create (IContext context)
Ninject.Activation.Context.Resolve ()
Ninject.KernelBase.<Resolve>b__4 (IContext context)
System.Linq.Enumerable+<CreateSelectIterator>c__Iterator10`2[Ninject.Activation.IContext,System.Object].MoveNext ()
System.Linq.Enumerable+<CreateCastIterator>c__Iterator0`1[SomeGameBehaviour].MoveNext ()
System.Linq.Enumerable.Single[SomeGameBehaviour] (IEnumerable`1 source, System.Func`2 predicate, Fallback fallback)
System.Linq.Enumerable.Single[SomeGameBehaviour] (IEnumerable`1 source)
Ninject.ResolutionExtensions.Get[SomeGameBehaviour] (IResolutionRoot root, Ninject.Parameters.IParameter[] parameters)
ObjectFactory.GetInstance[SomeGameBehaviour] () (at Assets/Scripts/Core/ObjectFactory.cs:31)
Grid.Start () (at Assets/Scripts/World/Grid.cs:27)


1 commentaires

Lorsque vous obtenez ce fonctionnement, vous devez tester votre plate-forme cible dès que possible. Les différentes plates-formes Unity3D n'ont pas nécessairement accès aux mêmes fonctionnalités mono que l'éditeur, en particulier du lecteur Web et du joueur iOS.


3 Réponses :


6
votes

Ninject exécute les actions d'activation après la création de l'objet. Dans ce cas, il s'agit de l'action d'activation d'injection de propriété. Il semble qu'il y ait un problème dans la partie de réflexion qui essaie d'obtenir les informations s'il ya un attribut d'injecteur sur une propriété de votre objet. C'est probablement un bogue dans Niject. Mais pour une enquête plus poussée, j'ai besoin d'informations:

  1. Êtes-vous sur la dernière version de NInject (2.2.1.0)?
  2. Quelle version utilisez-vous exactement? (E.G. .NET 4.0 NOWEB)
  3. Pouvez-vous déboguer le standardInjectionheung.ShouldInject de Ninject et enquêter sur quelle propriété causent le problème? Et voyez ce qui est spécial à propos de cette propriété? (E.G. Est-ce une propriété virtuelle qui est remplacée, existe-t-il d'autres propriétés avec le même nom, est-ce un indexeur, ...)

4 commentaires

Je l'ai retiré de Nuget la nuit dernière - c'est 2.2.1, .NET 3.5 Noweb. Au fait, l'unité utilise mono 2.6.5. Le seul moyen de déboguer dans l'unité est avec monodevelop et de le faire avec des dll externes, il a besoin de sa propre MDB, plutôt que d'un PDB. J'ai utilisé le convertisseur inclus et ses erreurs de lancement en essayant de le faire pour NINJECT, si malade doivent également extraire la source de pdb2mdb.exe aussi pour voir quoi de neuf!


Veuillez utiliser la version mono trouvée chez GitHub. github.com/ninject/ninject/downloads . Il vient avec MDB. Nuget ne prend pas en charge Mono en ce moment.


Avez-vous eu du succès débogué avec la version mono?


Toutes mes excuses pour ne pas répondre. Je n'avais pas de chance de déboguer avec Mono et je regarde comment je faisais mon di.



0
votes

Je veux ajouter quelque chose à ce sujet (bien que mon problème puisse être différent), car je voulais aussi utiliser Ninject dans un projet Unity3D.

Unlockily Ninject ne fonctionne pas dans Unity 3D 3,5 à l'aide de la mono développement compilé Version et le code source (2.2.1). P>

Cependant, en utilisant le code source, j'ai compris la raison: je devais d'abord désactiver manuellement tout le code relié à la définition Noweb (Unity3D de malheurement ne prend pas en charge le niveau de compilation Définit, si je ne me trompe pas), mais le véritable accident se produit à cause du code connexe no_assembly_scanning. Exactement dans Kernel.cs à ces lignes: P>

StandardKernel kernel = new StandardKernel();   

kernel.Bind<IKernel>().ToMethod(context => kernel);

kernel.Inject(ObjectWhichNeedsKernel)


3 commentaires

Je n'ai jamais utilisé l'unité3d moi-même. Ma meilleure hypothèse est de le mettre davantage vers le WP7 et SL construit depuis que Unity3D semble avoir des restrictions. Pouvez-vous s'il vous plaît essayer de supprimer la partie de génération de code aussi pour passer à la réflexion? Il y a deux façons de cela. On consiste à supprimer complètement le code en supprimant les pièces NO_LCG. Ou définissez la propriété UsereflectionBasedInjection dans les paramètres Ninject sur TRUE.


Également au lieu d'utiliser Inject Essayez d'utiliser Kernel.get () et laisser ninject créer l'instance. Et retirez la liaison du noyau. Ceci est déjà ajouté par le noyau.


Finalement, je décide de faire mon propre injecteur. Ce n'est pas mauvais, simple et axé sur l'unité. J'ai l'intention de créer un projet open source, mais je pense que cela prendra plus de temps.



5
votes

L'auteur de cet article http://outlinegames.com/2012/08/ 29 / TESTABILITÉ / Géré à Port Ninject à l'unité et il l'a appelée UnIject: https: // github .com / banderser / unIject

Cependant, je veux désigner ma solution (simple) aussi:

http://blog.sebaslab.com/ioc-container -for-unity3d-part-1 /
http://blog.sebaslab.com/ioc-container-for- Unity3D-Part-2 /

J'ai toujours besoin de remercier Remo Gloor, car grâce à lui, j'ai mieux compris le concept de conteneur de COI.


0 commentaires