2009-11-09 2 views
2

Le code ci-dessous produit cette sortie fin:Comment pouvez-vous instancier un objet avec une chaîne et envoyer un paramètre en C#?

This is page one. 
This is page two. 

Mais comment puis-je changer pour que les objets sont instanciés PageItem dynamiquement du List<string>?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace TestInstant 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> pageItemsIdCodes = new List<string>() { "PageItem1", "PageItem2" }; 
      PageItemManager pageItemManager = new PageItemManager(pageItemsIdCodes); 
      pageItemManager.DisplayMenu(); 

      Console.ReadLine(); 
     } 
    } 

    class PageItemManager 
    { 
     private Dictionary<string, BasePageItem> PageItemRecords = new Dictionary<string, BasePageItem>(); 
     public PageItemManager(List<string> pageItemsIdCodes) 
     { 
      //manually 
      PageItemRecords.Add("PageItem1", new PageItem1(this)); 
      PageItemRecords.Add("PageItem2", new PageItem2(this)); 

      //HOW DO i DO THIS DYNAMICALLY: 
      //PSEUDO-CODE: 
      //foreach (string pageItemIdCode in pageItemsIdCodes) 
      //{ 
      // Type t = Type.GetType(pageItemIdCode); 
      // //ERROR: Cannot implicitly convert type 'TestInstant.PageItemManager' to 'TestInstant.BasePageItem' 
      // BasePageItem pageItem = Activator.CreateInstance(t, new BasePageItem[] { this }); 
      // PageItemRecords.Add(pageItemIdCode, pageItem); 
      //} 

        //Type t = Type.GetType(pageItemIdCode); 
        //ERROR: Cannot implicitly convert type 'object' to 'TestInstant.BasePageItem'. 
        //BasePageItem pageItem = Activator.CreateInstance(t); // Change constructor 
        //pageItem.PageItemManager = this; // Add SetMananger call to BasePageItem 
        //PageItemRecords.Add(pageItemIdCode, pageItem); 

     } 

     public void DisplayMenu() 
     { 
      foreach (var pageItemRecord in PageItemRecords) 
      { 
       Console.WriteLine(pageItemRecord.Value.Title); 
      } 
     } 
    } 

    class BasePageItem 
    { 
     public string Title { get; set; } 
     protected PageItemManager pageItemManager; 
     public BasePageItem(PageItemManager pageItemManager) 
     { 
      this.pageItemManager = pageItemManager; 
     } 
    } 

    class PageItem1 : BasePageItem 
    { 
     public PageItem1(PageItemManager pageItemManager) 
      : base(pageItemManager) 
     { 
      Title = "This is page one."; 
     } 
    } 

    class PageItem2 : BasePageItem 
    { 
     public PageItem2(PageItemManager pageItemManager) 
      : base(pageItemManager) 
     { 
      Title = "This is page two."; 

     } 
    } 
} 

Répondre

8

Je crois que vous pouvez utiliser le Activator.CreateInstance qui prend des paramètres pour l'entrée.

foreach (string pageItemIdCode in pageItemsIdCodes) 
{ 
    Type t = Type.GetTypeFromProgID(pageItemIdCode); 
    Object pageItem = Activator.CreateInstance(t, new object[]{this}); 
    PageItemRecords.Add(pageItemIdCode, pageItem); 
} 

Ou comme le dit Groo, juste jeter:

foreach (string pageItemIdCode in pageItemsIdCodes) 
{ 
    Type t = Type.GetTypeFromProgID(pageItemIdCode); 
    BasePageItem pageItem = (BasePageItem)Activator.CreateInstance(t, new object[]{this}); 
    PageItemRecords.Add(pageItemIdCode, pageItem); 
} 

Vous pouvez également effectuer les opérations suivantes si vous voulez le type effectivement retourné:

foreach (string pageItemIdCode in pageItemsIdCodes) 
{ 
    Type t = Type.GetTypeFromProgID(pageItemIdCode); 
    BasePageItem pageItem = Activator.CreateInstance(t); // Change constructor 
    pageItem.SetMananger(this); // Add SetMananger call to BasePageItem 
    PageItemRecords.Add(pageItemIdCode, pageItem); 
} 

Voici l'exemple de travail complet :

using System; 
using System.Collections.Generic; 
using System.Text; 

namespace TestInstant 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> pageItemsIdCodes = new List<string>(); 
      pageItemsIdCodes.Add("PageItem1"); 
      pageItemsIdCodes.Add("PageItem2"); 
      PageItemManager pageItemManager = new PageItemManager(pageItemsIdCodes); 
      pageItemManager.DisplayMenu(); 

      Console.ReadLine(); 
     } 
    } 

    class PageItemManager 
    { 
     private Dictionary<string, BasePageItem> PageItemRecords = new Dictionary<string, BasePageItem>(); 
     public PageItemManager(List<string> pageItemsIdCodes) 
     { 
      //manually 
      //PageItemRecords.Add("PageItem1", new PageItem1(this)); 
      //PageItemRecords.Add("PageItem2", new PageItem2(this)); 

      foreach (string pageItemIdCode in pageItemsIdCodes) 
      { 
       Type t = Type.GetType("TestInstant."+pageItemIdCode); 
       BasePageItem pageItem = (BasePageItem)Activator.CreateInstance(t, new Object[] { this }); 
       PageItemRecords.Add(pageItemIdCode, pageItem); 
      } 

     } 

     public void DisplayMenu() 
     { 
      foreach (BasePageItem pageItemRecord in PageItemRecords.Values) 
      { 
       Console.WriteLine(pageItemRecord.Title); 
      } 
     } 
    } 

    class BasePageItem 
    { 
     private string mTitle; 
     public string Title { get { return mTitle; } set { mTitle = value; } } 
     protected PageItemManager pageItemManager; 
     public BasePageItem(PageItemManager pageItemManager) 
     { 
      this.pageItemManager = pageItemManager; 
     } 
    } 

    class PageItem1 : BasePageItem 
    { 
     public PageItem1(PageItemManager pageItemManager) 
      : base(pageItemManager) 
     { 
      Title = "This is page one."; 
     } 
    } 

    class PageItem2 : BasePageItem 
    { 
     public PageItem2(PageItemManager pageItemManager) 
      : base(pageItemManager) 
     { 
      Title = "This is page two."; 

     } 
    } 
} 
+0

Ce code obtient l'erreur que Add attend BasePageItem et nous envoyons l'objet, je l'ai modifié en conséquence dans mon exemple mais ne peut toujours pas obtenir la syntaxe correcte. –

+0

Copiez-le sur BasePageItem. – Groo

+0

Je veux envoyer "this" en tant que * paramètre * de la classe instanciée qui * hérite de * BasePageItem, puisque BasePageItem attend PageItemManager dans son constructeur, pas BasePageItem lui-même. –

1

Observez les surcharges pour Activator.CreateInstance. Vous pouvez passer dans les constructeurs dans un tableau d'objets pour un eux.

1

Puis-je su ggest Assembly.CreateInstance() Vous pouvez utiliser cette fonction pour créer une instance d'un assembly spécifié.

+0

Généralement vous utiliseriez 'Activator.CreateInstance' au lieu de' Assembly.CreateInstance', mais ce dernier est utile si vous devez créer le type à partir d'un assembly spécifique (par exemple, si deux assemblys ont le même type dans le même espace de noms). –

3

Cette compilation est réussie. Je viens de l'essayer.

foreach(string pageItemIdCode in pageItemsIdCodes) { 
    Type t = Type.GetType(pageItemIdCode); 
    BasePageItem pageItem = (BasePageItem) Activator.CreateInstance(t, new object[] { this }); 
    PageItemRecords.Add(pageItemIdCode, pageItem); 
} 

Il échoue à l'exécution parce que les pageItemIdCode valeurs sont incorrectes. Les changer comme suit:

List<string> pageItemsIdCodes = new List<string>() { "TestInstant.PageItem1", "TestInstant.PageItem2" }; 

rend le code exécuté avec succès.

Vous devez garder à l'esprit que les méthodes Reflection renvoient toujours null lorsqu'elles ne trouvent rien, plutôt que de déclencher une exception. Si votre code s'attend à ce que Type.GetType réussisse toujours, vous devez rechercher les valeurs NULL et générer votre propre exception, sinon vous obtiendrez des échecs en cascade car les valeurs NULL sont propagées via le reste du code.

+0

Intéressant: votre solution compile mais me donne une erreur d'exécution de "La valeur ne peut être nulle". Il semble vouloir lancer Activator.CreateInstance (...) à un moment où il est nul. Cela provoque la même erreur: BasePageItem pageItem = Activator.CreateInstance (t, nouvel objet [] {this}) en tant que BasePageItem; –

Questions connexes