I'd like to discuss about the best approach (in C#) to instantiate an object based on an input string. Let me explain.
Let'say I have a base class:
public abstract class BaseCar
{
public asbtract int GetEngineID();
//Other stuff...
}
Then I have several implementations of this class, let's say:
public class SportCar : BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
public class OtherCar: BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
And so on...
What I'd like to do is to make a static CarFactory class which has a CreateCar method which accepts a string as a parameter and returns a BaseCar instance, depending on what string you give. The string would be a name of a child class.
For example, if I call CarFactory.CreateCar('SportCar') it should return a SportCar instance.
I know I could use a simple switch statement to check which car has been requested and create a new instance based on that but I don't like this approach for two reasons:
I plan to have a lot of child classes, hard-coding every case wouldn't be too easy to mantain
I plan to implement an inizialization procedure to also give some initial values to the objects I create (using Reflection), so mixing hard-coding and reflection doesn't seem to be a good idea for me.
What I was thinking about is to use the Assembly.CreateInstance from System.Reflection to create an instance of the specified class but since this is the first time I approach this problem, I don't know if there are better ways to do that. Is this a valid approach ?
Considering the input string will come from an XML file, is there a simplier method ? Maybe my issue is already handled in some .NET Assembly which I'm missing.
Here is what I came up with. A generic factory class that automatically registers all types that are a subclass of the given type, and allows you to instantiate them via their name. This is somewhat related to the approach shown in the Java SO question linked by #Achilles in the comments, only that there is no initialisation function associated with the type.
There is no need to maintain an enum/switch combination of all types. It should also be somewhat easily extendable to handle your proposed reflection based initialisation.
static class StringFactory<T> where T : class
{
static private Dictionary<string, Type> s_dKnownTypes = new Dictionary<string, Type>();
static StringFactory()
{
RegisterAll();
}
static private void RegisterAll()
{
var baseType = typeof(T);
foreach (var domainAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in domainAssembly.GetTypes()
.Where(t => t.IsSubclassOf(baseType)))
{
s_dKnownTypes.Add(type.Name, type);
}
}
}
static public T Create(string _sTypeName)
{
Type knownType;
if (s_dKnownTypes.TryGetValue(_sTypeName, out knownType))
{
return (T)Activator.CreateInstance(knownType);
}
throw new KeyNotFoundException();
}
}
Assuming the classes of your question exist, you would instantiate a specific car like this:
var car = StringFactory<BaseCar>.Create("SportsCar");
DoSomethingWith(car.EngineID());
Since your question was for a discussion about the best approaches, please consider this only one of them. I have not used this in a production environment, and it is entirely possible that it is the wrong approach to your specific situation. It works well enough to show the general principle, however, and should provide a starting point for further discussion.
Related
So I got an assignment [college student] to create a program that runs a garage. I have a class for every car type [FuelMotorcycle, ElectricMotorcycle, FuelCar, ElectricCar, etc.], each car type has its own constructor and they all differ from one another.
One of the assignment requirements is to "place the code that creates car objects [new], and this code alone, in a class on the logical part of the program, this code part cannot turn to the user directly or indirectly" (translated).
So the way I see it, I have a class, let's say "EmptyCarCreator" , that will have methods such as:
public static FuelMotorcycle CreateNewFuelMotorcycle()
{
FuelMotorcycle EmptyFuelMotorcycle;
return EmptyFuelMotorcycle;
}
obviously this won't compile, and even if it did, I couldn't use the "FuelMotorcycle" class constructor after I get it returned.
I need the user to input the elements for the constructor.
So, is there any other way to do this? I feel like I am missing something very basic here.
Please excuse any English errors, hope my question was clear.
You would need something like this:
public static class EmptyCarCreator
{
public static T Create<T>() where T : class, new()
{
return new T();
}
}
Then you would use it like this:
FuelMotorcycle myVehicle = EmptyCarCreator.Create<FuelMotorcycle>();
This will create a new class through the parameterless constructor.
There are other options that might be able to handle parameters a little better like this:
public static class EmptyCarCreator
{
public static object Create(Type type)
{
return Activator.CreateInstance(type);
}
}
To use this you would have to cast this returned object.
FuelMotorcycle myVehicle = (FuelMotorcycle)EmptyCarCreator.Create(typeof(FuelMotorcycle));
Hello I'm using Visual Studio 2005 (because I need compact framework support) and my problem is with generics.
I have created an abstract class called AbstractDAO which is my base
From that I am creating other classes like DocumentDAO,HeaderDAO etc which represent different tables on my database
What I wish to do is retrieve a certain number of the above mentioned DAO classes, but as an AbstractDAO (the abstract class has a number of concrete implementations that I wish to use)
What I tried is
AbstractDAO<object> dao = new DocumentDAO();
AbstractDAO<object> dao = (AbstractDAO<object>)new DocumentDAO();
AbstractDAO<T> dao = new DocumentDAO();
I need the above because I have created a function that transfers data from one table to another similar table in a different database, so it would (if it worked) go something like this
AbstractDAO<object> dao_local = new DocumentDAO(local_database);
AbstractDAO<object> dao_remote = new DocumentDAO(remote_database);
do_transfer(dao_local,dao_remote)
void do_transfer(AbstractDAO<object> from, AbstractDAO<object> to) {
List<object> items = from.get_all();
to.insert(items);
}
Is there any way to do the above?
That will only work if your class hierachy is like this:
class DocumentDAO : AbstractDAO<object> {
//...
}
By your comment it seems like you have a type hierarchy like this:
class DocumentDAO : AbstractDAO<SomeType> {
public override SomeType Foo() {
//...
return someValue;
}
//...
}
class AbstractDAO<T> {
public abstract T Foo();
//...
}
You probably want to refactor AbstractDAO to implement a non generic interface like IAbstractDAO:
class IAbstractDAO {
object Foo();
//...
}
class AbstractDAO<T> {
public object Foo() {
return Foo();
}
public abstract T Foo();
//...
}
Any implementation of AbstractDAO<T> is compiled to a separate object type where T is replaced with the type. See "Is generics runtime or compile time polymorphism?" for more information on how this happens. In short, don't let the <T> fool you.
This means that you can't assign DocumentDAO to AbstractDAO<object> any more than you can assign String to it. Also a generic type is not the same as inheriting, which seems to be what you are trying to achieve.
In either case there are two standard solutions, as already mentioned.
The first is to operate on interfaces. You create an interface for the common properties and have AbstractDAO<T> or any other inherit from this. Then most of the time you simply operate on interfaces. Exactly how you organize it is up to you.
The second is to perform a shallow copy of the object. This means copying values and references from one object to the other. For this you usually use an object mapper like AutoMapper. This tutorial should get you started..
You can try to use Automapper to transfer your objects like this:
void do_transfer(AbstractDAO<FirstType> from, AbstractDAO<SecondType> to)
{
Mapper.Initialize(cfg=>cfg.CreateMap<FirstType, SecondType>);
List<FirstType> fromItems = from.get_all();
List<SecondType> itemsToInsert =
Mapper.Map<List<FirstType>, List<SecondType>>(fromItems);
to.insert(itemsToInsert);
}
By default automapper will map fields with same names. You can create configurations for complex type mapping.
So I finally found the answer to what I was trying to do, instead of assigning abstractDAO to something I created a factory that would retrieve the required AbstractDAO according to what type the generic was, and used this function
private bool transfer<T>(){
AbstractDAO<T> local = DAOFactory.get<T>(local_database);
AbstractDAO<T> remote = DAOFactory.get<T>(remote_database);
List<T> items = local.get_all();
foreach (T item in items) {
remote.insert(item);
}
}
That way I can call this function like this:
transfer< Document >();
transfer< Header >();
etc. and do a full transfer
edit: just for completeness' shake this is the factory I created
public static AbstractDAO<T> get<T>(Database database) {
Type t = typeof(T);
if (t == typeof(Document)) {
return new DocumentDAO(database) as AbstractDAO<T>;
} else if (t == typeof(Header)) {
return new HeaderDAO(database) as AbstractDAO<T>;
} etc.
}
Hello guys i am having trouble designing an object repository for a game:
class ObjectRepository
{
private readonly LevelType _levelType;
private readonly BaseObject[] _darkForestObjects = new BaseObject[]
{ new DarkForestTreeA(), new DarkForestTreeB(), new DarkForestTreeC() };
private readonly BaseObject[] _lightForestObjects = new BaseObject[]
{ new LightForestTreeA(), new LightForestTreeB(), new LightForestTreeC() };
public ObjectRepository(LevelType lt)
{
_levelType = lt;
}
public BaseObject GetObject(int obj)
{
if (obj < 0 || obj > _darkForestObjects.Length)
{
Debug.LogError("Object does not exist.");
return null;
}
switch (_levelType)
{
case LevelType.DarkForest:
return _darkForestObjects[obj];
case LevelType.LightForest:
return _lightForestObjects[obj];
}
return null;
}
}
public enum LevelType
{
DarkForest = 0,
LightForest = 1,
}
I am searching for a way of automating this class.By automating it i mean that i don't want every time i create a new object deriving from BaseObject to come inside the Repository class and modify arrays.It just doesn't seem natural.Can anybody point me out a suggestion for automation?
I'll take a gander at this, so please let me know if I'm assuming things wrong.
You'll need:
A repository that'll hold your BaseObject-derived instances;
Said repository must be accessible by the BaseObject class;
Whenever a BaseObject is created, it adds itself to the repository.
Now, I've noticed that you hold instances for both dark and light versions of your objects. So I'd additionally suggest a holder class for both light and dark versions of a given 'object'. Like this:
class CompoundObject
{
public BaseObject LightVersion;
public BaseObject DarkVersion;
}
Your repository then hold CompoundObject-derived objects, and instead of BaseObject objects adding themselves at creation time, CompoundObject objects would do it.
Now about Array manipulations, you may be right; it can be somewhat clunky. I'd suggest the adoption of List<CompoundObject> instead of CompoundObject[]. A generic List offer very handy methods like Add and Remove that can streamline your collection manipulation.
If I were you, I would opt for a more generic solution using interfaces.
Considering your example, I assume that you have multiple level types which have their own specific TreeA, TreeB and TreeC implementations.
If I understood right, I would rather use interface for each tree type. Example for TreeA :
public interface ITreeA
{
// any common public members here
}
public class DarkForestTreeA : ITreeA, BaseObject
{
...
}
public class LightForestTreeA : ITreeA, BaseObject
{
...
}
This way, you can ask your repository to provide the ITreeA implementation specific to the level type. Something like :
public T GetObject<T>() // where T could be ITreeA, ITreeB...
{
...
}
So you could call myRepo.GetObject() and get a DarkForestTreeA object if level type is DarkForest for example.
To have this behavior "automated", you could declare all the specific implementations of DarkForest in a unique namespace and then use reflexion to find the class of the namespace that implements ITreeA for example. This may not be very efficient in terms of performance but it gives you great flexibility as you will just have to add new classes in your namespace to have them available from the repository. However, it can also bring other problems (for example, what would happen if you have two classes implementing ITreeA in the same namespace ?).
See Getting all types in a namespace via reflection and Getting all types that implement an interface with C# 3.0 for implementation details.
I have to admit it isn't the simplest solution.
You could consider simpler thing like defining a dictionary for object type (treeA, treeB) and then define a dictionary for each level type mapping the object type to its concrete implementation.
For example :
public enum ObjectType
{
TreeA,
TreeB,
TreeC,
}
Dictionary<ObjectType, Type> DarkForestObjectTypes = new Dictionary<ObjectType, Type>()
{
{ ObjectType.TreeA, typeof(DarkForestTreeA) },
{ ObjectType.TreeB, typeof(DarkForestTreeB) }
...
}
I won't go into more details as this answer looks a bit messy but hopefully it will give you ideas to go on with.
I have a class of 3 different linked lists (for saving the entities in a game I'm working on). The lists are all of objects with the same base type, but I keep them separate for processing reasons. Note that IEntity, IObject and IUndead all inherited from IEntity.
public class EntityBucket
{
public LinkedList<IEntity> undeadEntities;
public LinkedList<IEntity> objects;
public LinkedList<IEntity> livingEntities;
public EntityBucket()
{
undeadEntities = new LinkedList<IEntity>();
objects = new LinkedList<IEntity>();
livingEntities = new LinkedList<IEntity>();
}
public LinkedList<IEntity> GetList(IObject e)
{
return objects;
}
public LinkedList<IEntity> GetList(IUndead e)
{
return undeadEntities;
}
public LinkedList<IEntity> GetList(ILiving e)
{
return livingEntities;
}
}
I have 3 methods for retrieving each of the lists, currently based on their parameters. The fact that there are 3 is fine, since I know each list will in some way or another require its own accessor. Passing an instantiated object is not ideal though, as I may want to retrieve a list somewhere without having an object of similar type at hand. Note that the object here is not even used in the GetList methods, they are only there to determine which version to use. Here is an example where I have an instantiated object at hand:
public void Delete(IUndead e, World world)
{
.....
LinkedList<IEntity> list = buckets[k].GetList(e);
.....
}
I don't like this current implementation as I may not always have an instantiated object at hand (when rendering the entities for example). I was thinking of doing it generically but I'm not sure if this is possible with what I want to do. With this I also need 3 Delete methods (and 3 of any other, such as add and so forth) - one for each type, IUndead, IObject and ILiving. I just feel that this is not the right way of doing it.
I'll post what I have tried to do so far on request, but my generics is rather bad and I feel that it would be a waste for anyone to read this as well.
Finally, performance is very important. I'm not prematurely optimizing, I am post-optimizing as I have working code already, but need it to go faster. The getlist methods will be called very often and I want to avoid any explicit type checking.
So you want a better interface, because, as you said, passing an unnecessary object to GetList just to figure out its type makes little sense.
You could do something like:
public List<IEntity> GetList<T>() : where T:IEntity
{
if(typeof(T)==typeof(IUndead)) return undedEntities;
// and so on
}
And you'll have to call it like this: GetList<IUndead>();
I think an enum is a better idea here:
enum EntityTypes { Undead, Alive, Object };
public List<IEntity> GetList(EntityTypes entityType) { ... }
It's cleaner and makes more sense to me.
EDIT: Using generics is actually not that simple. Someone could call GetList a Zombie type, which implements IUndead, and then you'll have to check for interface implementations. Someone could even pass you a LiveZombie which implements both IUndead and IAlive. Definitely go with an enum.
How about a better implementation to go with that better interface?
public class EntityBucket
{
public LinkedList<IEntity> Entities;
public IEnumerable<T> GetEntities<T>() where T : IEntity
{
return Entities.OfType<T>();
}
}
List<IUndead> myBrainFinders = bucket.GetEntities<IUndead>().ToList();
With this implementation, the caller better add each item to the right list(s). That was a requirement for your original implementation, so I figure it's no problem.
public class EntityBucket
{
Dictionary<Type, List<IEntity>> entities = new Dictionary<Type, List<IEntity>>();
public void Add<T>(T item) where T : IEntity
{
Type tType = typeof(T);
if (!entities.ContainsKey(tType))
{
entities.Add(tType, new List<IEntity>());
}
entities[tType].Add(item);
}
public List<T> GetList<T>() where T : IEntity
{
Type tType = typeof(T);
if (!entities.ContainsKey(tType))
{
return new List<T>();
}
return entities[tType].Cast<T>().ToList();
}
public List<IEntity> GetAll()
{
return entities.SelectMany(kvp => kvp.Value)
.Distinct() //to remove items added multiple times, or to multiple lists
.ToList();
}
}
How about something like the following?
public LinkedList<IEntity> GetList(Type type) {
if (typeof(IUndead).IsAssignableFrom(type)) return undeadEntities;
if (typeof(ILiving).IsAssignableFrom(type)) return livingEntities;
if (typeof(IObject).IsAssignableFrom(type)) return objects;
}
Then you would call it like this:
var myUndeads = GetList(typeof(IUndead));
var myLivings = GetList(typeof(ILiving));
// etc
The same type of logic could be implemented in your deletes, add, and other methods, and you never need a concrete instance of an object to access them.
The IsAssignableFrom logic handles subclassing just fine (i.e. you could have a CatZombie, which derives from Zombie, which implements IUndead, and this would still work). This means you still only have to create one Delete method, something like the following:
public void Delete(IEntity e, World world) {
if (typeof(IUndead).IsAssignableFrom(type)) undeadEntities.Remove(e);
if (typeof(ILiving).IsAssignableFrom(type)) livingEntities.Remove(e);
if (typeof(IObject).IsAssignableFrom(type)) objects.Remove(e);
}
EDIT: I noticed your comment on zmbq's answer regarding performance; this is definitely NOT fast. If you need high performance, use an enum-style approach. Your code will be more verbose and require more maintenance, but you'll get much better performance.
Seems to me you could just implement a Dictionary
of named LinkedList's and refer to them
by name or enum.
That way adding or removing lists is just an
implementation issue and no separate class to deal with.
I am not sure how to implement what I have in mind using C# .Net 3.5. I have a static class called Common which contains common methods. One of the method is PrepareReportParameters. This method accepts a string ReportParams and parse it to get the parameter values. I load this ReportParams string into a Dictionary . And then verify whether the required elements exist. I check that like:
if (ReportParamList.ContainsKey("PAccount"))
{
ReportParamList.TryGetValue("PAccount", out PrimaryAccount);
}
where PrimaryAccount is a static variable in my Common class. And I can access this elsewhere as Common.PrimaryAccount.
Though, this approcah of accessing the report parameters will work but I want PrimaryAccount to be accessed as Common.ReportParameters.PrimaryAccount.
Here is the problem, I don't know what type ReportParameters should be and how can I have all the report parameters added to this type? How should I define ReportParameters? Does it sound feasible or it doesn't make any sense. Please H E L P!
It sounds like you're basically used to using global variables to pass around state. That's generally a really bad idea.
Why doesn't your method just return the primary account value? That can then be passed to other things which need it.
If you find yourself with a lot of static members - and in particular if other classes are fetching mutable static variables - consider whether there's a more OO design you could apply. It'll be easier to understand, easier to test, and easier to maintain.
EDIT: Okay, so currently you have:
public static class Common
{
public static int PrimaryAccount;
// other static fields
public static void PrepareReportParameters(string reportParameters)
{
// Code to set the fields
}
}
Instead of that, use a normal class:
public class ReportParameters
{
public int PrimaryAccount { get; private set; }
// Other properties
private ReportParameters(int primaryAccount, ....)
{
this.PrimaryAccount = primaryAccount;
}
// Could use a constructor instead, but I prefer methods when they're going to
// do work
public static ReportParameters Parse(string report)
{
// Parse the parameter, save values into local variables, then
return new ReportParameters(primaryAccount, ...);
}
}
Then call this from the rest of your code, and pass the ReportParameters reference to anything that needs it.
You could create a class called ReportParameters with the relevant strongly-typed properties, and give Common a static instance of it?
I'm not sure this is the best design. Theres a certain amount of 'code smell' to having Common.PrimaryAccount only to be allowed to be accessed after PrepareReportParameters is called. Maybe you'd consider an instance class, passing in the parameters in the constructor?