Domanda

Il codice riportato di seguito si compone di due classi:

  • SmartForm (semplice modello di classe)
  • SmartForms (plurale classe che contiene una raccolta di SmartForm gli oggetti)

Voglio essere in grado di creare un'istanza sia singolare e plurale classi come questo (cioèNon voglio un metodo factory GetSmartForm()):

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

Per consolidare la logica, solo il plurale di classe deve accedere al database.Il singolare di classe, quando gli viene chiesto di creare un'istanza di se stesso, semplicemente creare un'istanza di un plurale di classe, quindi scegliere l'oggetto del plurale dell'oggetto di raccolta e diventare l'oggetto.

Come faccio a fare che? Ho provato ad assegnare l'oggetto this che non funziona.

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;
            }
        }
    }
}
È stato utile?

Soluzione

Non deve essere esattamente lo stesso oggetto, si deve solo sembrano essere lo stesso per gli osservatori esterni. Se si copia tutti i dati da un oggetto all'altro, si compirà la stessa cosa.

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

Altri suggerimenti

Non è possibile ottenere un oggetto per "diventare" un altro.

Utilizzare metodi statici invece di costruttori (e i costruttori privati/interni/qualunque cosa, in modo che solo i metodi statici possono accedere).Ci sono numerosi vantaggi di utilizzare metodi statici su costruttori:

  • È possibile restituire null se del caso
  • È possibile restituire un oggetto esistente, se del caso
  • Si può fare un sacco di lavoro e quindi chiamare un costruttore semplice che solo set di campi

Il rovescio della medaglia è che non funzionano con C#/insieme gli inizializzatori di oggetto :(

Un'alternativa ai metodi statici (che non funzionano bene con la dependency injection, è vero) è quello di avere un separato in fabbrica e chiamare i metodi di istanza che.

Non è possibile. Microsoft fa questo attraverso la definizione di un public static metodo Create (), invece. Si veda ad esempio WebRequest e HttpWebRequest nello spazio dei nomi System.Net. Vi suggerisco di fare lo stesso.

Rendere il costruttore della classe base interno o privato, quindi non può essere istanziata direttamente. O meglio ancora, ne fanno una classe astratta. Fare uso dei costruttori nascosti nel vostro Create () implementazione.

È possibile usare un internal o modificatore di protected per il costruttore, invece di public. Tale che:

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

diventa:

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

Si potrebbe fare una classe privata chiamata SmartFormData, e mettere tutti i valori in esso.

rendere la classe plurale SmartForms mantenere una collezione di questi oggetti, e rendere il costruttore singolare SmartForm trovare il giusto esempio SmartFormData in SmartForms plurale.

Poi, fare tutte le proprietà in SmartForm singolare prendere i loro valori da SmartFormData

Tuttavia, il modo migliore per farlo è quello di avere un costruttore privato e utilizzare un metodo factory.

C'è un motivo che è necessario utilizzare un costruttore?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top