2009-06-09 7 views
0

Le code suivante se compose deux cours:Comment puis-je forcer un constructeur C# à être une usine?

  • SmartForm (classe simple modèle)
  • SmartForms (classe plurielle qui contient une collection de SmartForm objets)

Je veux être capable d'instancier à la fois les classes au singulier et au pluriel comme ça (c.-à-d. Je ne veux pas une méthode de fabrication GetSmartForm()):

SmartForms smartForms = new SmartForms("all"); 
SmartForm smartForm = new SmartForm("id = 34"); 

Pour consolider la logique, seule la classe plurielle devrait accéder à la base de données. La classe singulière, lorsqu'on lui demande de s'instancier, instanciera simplement une classe plurielle, puis choisira l'objet parmi la collection de l'objet pluriel et deviendra cet objet.

Comment faire cela? J'ai essayé d'assigner l'objet à this qui ne fonctionne pas.

using System.Collections.Generic; 

namespace TestFactory234 
{ 
    public class Program 
    { 
     static void Main(string[] args) 
     { 
      SmartForms smartForms = new SmartForms("all"); 
      SmartForm smartForm = new SmartForm("id = 34"); 
     } 
    } 

    public class SmartForm 
    { 
     private string _loadCode; 

     public string IdCode { get; set; } 
     public string Title { get; set; } 

     public SmartForm() {} 

     public SmartForm(string loadCode) 
     { 
      _loadCode = loadCode; 
      SmartForms smartForms = new SmartForms(_loadCode); 
      //this = smartForms.Collection[0]; //PSEUDO-CODE 
     } 

    } 

    public class SmartForms 
    { 
     private string _loadCode; 

     public List<SmartForm> _collection = new List<SmartForm>(); 
     public List<SmartForm> Collection 
     { 
      get 
      { 
       return _collection; 
      } 
     } 

     public SmartForms(string loadCode) 
     { 
      _loadCode = loadCode; 
      Load(); 
     } 

     //fills internal collection from data source, based on "load code" 
     private void Load() 
     { 
      switch (_loadCode) 
      { 
       case "all": 
        SmartForm smartFormA = new SmartForm { IdCode = "customerMain", Title = "Customer Main" }; 
        SmartForm smartFormB = new SmartForm { IdCode = "customerMain2", Title = "Customer Main2" }; 
        SmartForm smartFormC = new SmartForm { IdCode = "customerMain3", Title = "Customer Main3" }; 
        _collection.Add(smartFormA); 
        _collection.Add(smartFormB); 
        _collection.Add(smartFormC); 
        break; 
       case "id = 34": 
        SmartForm smartForm2 = new SmartForm { IdCode = "customerMain2", Title = "Customer Main2" }; 
        _collection.Add(smartForm2); 
        break; 
       default: 
        break; 
      } 
     } 
    } 
} 

Répondre

4

Il ne doit pas être exactement le même objet, il doit juste sembler être le même pour les observateurs externes. Si vous copiez toutes les données d'un objet à un autre, cela aboutira à la même chose.

public SmartForm(string loadCode) 
{ 
    _loadCode = loadCode; 
    SmartForms smartForms = new SmartForms(_loadCode); 
    this.IdCode = smartForms[0].IdCode; 
    this.Title = smartForms[0].Title; 
} 
+0

Exactement, je cherche quelque chose comme ça, tout ce dont j'ai besoin sont des propriétés simples, mais il faut que ce soit dynamique pour tout type d'objet, je pense à une classe de "clonage par réflexion", isn ' t-il quelque chose comme ça, par exemple System.Reflection.Clone (smartForms [0])? –

2

Vous pouvez utiliser un modificateur internal ou protected pour le constructeur, au lieu de public. Tel que:

public SmartForm() {} 
public SmartForm(string loadCode) 
{ 
    _loadCode = loadCode; 
    SmartForms smartForms = new SmartForms(_loadCode); 
    //this = smartForms.Collection[0]; //PSEUDO-CODE 
} 

devient:

internal SmartForm() {} 
internal SmartForm(string loadCode) 
{ 
    _loadCode = loadCode; 
    SmartForms smartForms = new SmartForms(_loadCode); 
    //this = smartForms.Collection[0]; //PSEUDO-CODE 
} 
7

Vous ne pouvez pas obtenir un objet à un autre "devenir".

Utilisez des méthodes statiques à la place des constructeurs (et rendez les constructeurs private/internal/whatever de sorte que seules les méthodes statiques puissent y accéder). Il existe de nombreux avantages à l'utilisation de méthodes statiques sur les constructeurs:

  • Vous pouvez retourner null le cas échéant
  • Vous pouvez retourner un objet existant le cas échéant
  • Vous pouvez faire beaucoup de travail et puis appel simple constructeur qui définit simplement les champs

L'inconvénient est qu'ils ne fonctionnent pas avec C# collection/objet initializers :(

Une alternative aux méthodes statiques (qui ne fonctionnent pas bien avec l'injection de dépendances, certes) est d'avoir une fabrique séparée et des méthodes d'instance d'appel sur cela.

3

Vous ne pouvez pas. Microsoft le fait en définissant une méthode publique Create() statique à la place. Voir par exemple WebRequest et HttpWebRequest dans l'espace de noms System.Net. Je vous conseille de faire de même.

Rendre le constructeur de la classe de base interne ou privé, il ne peut donc pas être directement instancié. Ou mieux encore, en faire une classe abstraite.Utilisez les constructeurs cachés dans votre implémentation Create().

0

Vous pourriez faire une classe privée appelée SmartFormData, et de mettre toutes les valeurs en elle.

Faire la classe SmartForms pluriel maintenir une collection de ces objets, et faire le constructeur SmartForm singulier trouver l'instance droite SmartFormData au pluriel SmartForms.

Ensuite, faire toutes les propriétés en SmartForm singulier aller chercher leurs valeurs de SmartFormData

Cependant, la meilleure façon de le faire est d'avoir un constructeur privé et utiliser une méthode de fabrication.

Y a-t-il une raison pour laquelle vous devez utiliser un constructeur?