Как я могу заставить конструктор C # быть фабрикой? - PullRequest
0 голосов
/ 09 июня 2009

Код ниже состоит из двух классов :

  • SmartForm (простой класс модели)
  • SmartForms (множественный класс, содержащий коллекцию объектов SmartForm )

Я хочу иметь возможность создавать экземпляры классов единственного и множественного числа вот так (т.е. я не хочу фабричный метод GetSmartForm ()):

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

Чтобы объединить логику, только множественный класс должен иметь доступ к базе данных . Класс единственного числа, когда его просят создать экземпляр, просто создает экземпляр класса множественного числа, затем выбирает один объект из коллекции объекта множественного числа и становится этим объектом .

Как мне это сделать? Я пытался присвоить объекту this, который не работает.

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;
            }
        }
    }
}

Ответы [ 5 ]

7 голосов
/ 09 июня 2009

Нельзя заставить один объект "стать" другим.

Используйте статические методы вместо конструкторов (и сделайте конструкторы приватными / внутренними / какими угодно, чтобы только статические методы могли получить к ним доступ). Использование статических методов перед конструкторами дает множество преимуществ:

  • При необходимости вы можете вернуть ноль
  • При необходимости вы можете вернуть существующий объект
  • Вы можете сделать много работы и затем вызвать простой конструктор, который просто устанавливает поля

Недостатком является то, что они не работают с инициализаторами коллекции / объекта C #: (

Альтернатива статическим методам (которые не очень хорошо работают с внедрением зависимостей, по общему признанию) состоит в том, чтобы иметь отдельную фабрику и вызывать методы экземпляра для этого.

4 голосов
/ 09 июня 2009

Это не обязательно должен быть один и тот же объект, просто он должен казаться одинаковым для внешних наблюдателей. Если вы скопируете все данные из одного объекта в другой, это сделает то же самое.

public SmartForm(string loadCode)
{
    _loadCode = loadCode;
    SmartForms smartForms = new SmartForms(_loadCode);
    this.IdCode = smartForms[0].IdCode;
    this.Title = smartForms[0].Title;
}
3 голосов
/ 09 июня 2009

Вы не можете. Microsoft делает это, определяя открытый статический метод Create (). См., Например, WebRequest и HttpWebRequest в пространстве имен System.Net. Я предлагаю вам сделать то же самое.

Сделать конструктор базового класса внутренним или закрытым, чтобы его нельзя было напрямую создать. Или еще лучше, сделайте это абстрактным классом. Используйте скрытые конструкторы в вашей реализации Create ().

2 голосов
/ 09 июня 2009

Вы можете использовать модификатор internal или protected для конструктора вместо public. Такие что:

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

становится:

internal SmartForm() {}
internal SmartForm(string loadCode)
{
    _loadCode = loadCode;
    SmartForms smartForms = new SmartForms(_loadCode);
    //this = smartForms.Collection[0]; //PSEUDO-CODE
}
0 голосов
/ 09 июня 2009

Вы можете создать закрытый класс с именем SmartFormData и поместить в него все значения.

Заставьте класс SmartForms во множественном числе поддерживать коллекцию этих объектов, а конструктору SmartForm найдите правильный экземпляр SmartFormData в SmartForms множественном числе.

Затем все свойства в SmartForm единственном числе извлекают их значения из SmartFormData

Однако лучший способ сделать это - иметь приватный конструктор и использовать фабричный метод.

Есть ли причина, по которой вы должны использовать конструктор?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...