Reputation: 193462
The code below consists of two classes:
I want to be able to instantiate both singular and plural classes like this (i.e. I don't want a factory method GetSmartForm()):
SmartForms smartForms = new SmartForms("all");
SmartForm smartForm = new SmartForm("id = 34");
To consolidate logic, only the plural class should access the database. The singular class, when asked to instantiate itself, will simply instantiate a plural class, then pick the one object out of the the plural object's collection and become that object.
How do I do that? I tried to assign the object to this
which doesn't work.
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;
}
}
}
}
Upvotes: 0
Views: 2229
Reputation: 888203
You could make a private class called SmartFormData
, and put all of the values into it.
Make the SmartForms
plural class maintain a collection of those objects, and make the SmartForm
singular constructor find the right SmartFormData instance in SmartForms
plural.
Then, make all of the properties in SmartForm
singular fetch their values from SmartFormData
However, the best way to do it is to have a private constructor and use a factory method.
Is there a reason that you have to use a constructor?
Upvotes: 0
Reputation: 6378
It doesn't have to be exactly the same object, it just has to appear to be the same to external observers. If you copy all the data from one object to another, it will accomplish the same thing.
public SmartForm(string loadCode)
{
_loadCode = loadCode;
SmartForms smartForms = new SmartForms(_loadCode);
this.IdCode = smartForms[0].IdCode;
this.Title = smartForms[0].Title;
}
Upvotes: 4
Reputation: 48516
You cannot. Microsoft does this by defining a public static Create() method instead. See for example WebRequest and HttpWebRequest in the System.Net namespace. I suggest you do the same.
Make the base class' constructor internal or private, so it cannot be directly instantiated. Or better yet, make it an abstract class. Make use of the hidden constructors in your Create() implementation.
Upvotes: 3
Reputation: 1503769
You can't get one object to "become" another.
Use static methods instead of constructors (and make the constructors private/internal/whatever so that only the static methods can access them). There are numerous benefits to using static methods over constructors:
The downside is they don't work with C# collection/object initializers :(
An alternative to static methods (which don't work well with dependency injection, admittedly) is to have a separate factory and call instance methods on that.
Upvotes: 7
Reputation: 20203
You could use an internal
or protected
modifier for the constructor, instead of public
. Such that:
public SmartForm() {}
public SmartForm(string loadCode)
{
_loadCode = loadCode;
SmartForms smartForms = new SmartForms(_loadCode);
//this = smartForms.Collection[0]; //PSEUDO-CODE
}
becomes:
internal SmartForm() {}
internal SmartForm(string loadCode)
{
_loadCode = loadCode;
SmartForms smartForms = new SmartForms(_loadCode);
//this = smartForms.Collection[0]; //PSEUDO-CODE
}
Upvotes: 2