2012-06-20 6 views
3

J'ai un projet sur lequel je ne sais pas quelle classe je devrais instancier lors de la compilation. J'essaie d'utiliser Activator.CreateInstance() pour générer une nouvelle classe pour moi en fonction de l'entrée de l'utilisateur. Le code ci-dessous fonctionne bien, mais j'ai dû changer mon constructeur sur mes classes INECCQuery pour avoir seulement un constructeur par défaut et n'utiliser aucune sorte d'injection de dépendance. Est-ce que je peux toujours utiliser mes liaisons d'injection et l'Activator.CreatInstance()? J'utilise Ninject pour l'injection.Activator.CreateInstance et Ninject

[HttpGet] 
    public ActionResult Index(string item) { 
     Type t = Type.GetType(string.Format("Info.Audit.Query.{0}Query, Info.Audit", item.ToUpper())); 
     if (t != null) { 
     INECCQuery query = (INECCQuery)Activator.CreateInstance(t); 
     var results = query.Check(); 
     return View("Index", results); 
     } 
     return View("Notfound"); 
    } 

Répondre

3

injection Constructor est toujours préférable, si possible, mais une sauvegarde appropriée serait de tirer parti de l'injection de la propriété.

http://ninject.codeplex.com/wikipage?title=Injection%20Patterns

class SomeController { 

    [Inject] 
    public Object InjectedProperty { get; set; } 

} 

Sur la base de l'hypothèse que vous essayez de remplacer le Activator.CreateInstance vous pouvez injecter un Func<T, INECCQuery> ou quel que soit l'usine que vous souhaitez utiliser.

+0

@zespri, comment faites-vous la distinction entre 'Activator.CreateInstance' et 'construire un objet par réflexion'? –

2

Vous pouvez obtenir que Ninject vous donne un objet de type t lors de l'exécution et reçoive toujours l'injection de dépendance via le constructeur .... Je fais quelque chose de similaire pour un cas dans mon application.

Dans le fichier Global.asax.cs, j'ai la méthode suivante:

/// <summary> 
    /// Gets the instance of Type T from the Ninject Kernel 
    /// </summary> 
    /// <typeparam name="T">The Type which is requested</typeparam> 
    /// <returns>An instance of Type T from the Kernel</returns> 
    public static T GetInstance<T>() 
    { 
     return (T)Kernel.Get(typeof(T)); 
    } 

Cela dépend d'une référence statique du noyau.

Ensuite, dans le code, je

var myInfrastructureObject = <YourAppNameHere>.GetInstance<MyInfrastructureType>(); 

Alors, je sais le type à la compilation alors que vous ne faites pas, mais ce ne serait pas si difficile de changer cela.

Vous pouvez également consulter le modèle ServiceLocator.

0

J'ai découvert que vous pouviez simplement passer une seconde option à la méthode Activator.CreateInstance et tant qu'elle correspond à la signature de votre constructeur, cela fonctionnera. Le seul problème est que si vos paramètres ne correspondent pas, vous obtiendrez une erreur d'exécution.

Type t = Type.GetType(string.Format("Info.Audit.Query.{0}Query, Info.Audit", item.ToUpper())); 
INECCQuery query = (INECCQuery)Activator.CreateInstance(t, repository); 

Merci pour toute l'aide.