dragnash
dragnash

Reputation: 105

C# - Factory pattern using reflection or how?

I'm developing a game in console c#, that you can read maps created in files. For doing so, i'm reading a file and storing that into a string. Then i'm reading each character individually and depending on the character, I need to create an object using the factory pattern. I don't know how to do it without coupling the code.

I have the main entity Object. From object inherit different objects, like: Box, Wall, Grass, Tree. Each one is represented by a character in the file and translated to another character in the game, (B)ox = '■', (W)all = '▓', (G)rass = 'v', (T)ree = '↑'. The way I done that is by placing a property char "Model" in the Object with getter only, and in each object I override the getter with the corresponding model.

Now, while I'm reading the file map mentioned before I need to tell the factory which object to build depending on the character read. I dont want to make a big switch(character) because it will be coupled, because for each object I want to add I will have to add a new case in the switch. Is any better way of doing so?

Example of class Box:

public class Box : Object
{
    public override char Model { get { return '■'; } }

    public Box()
    {
        this.Name = "box";
        this.MapCharacter = 'B';
        this.Colors = new List<ConsoleColor>() { ConsoleColor.DarkYellow };
        this.Destructible = true;
        this.Passable = false;
        this.SeeThrough = false;
        this.Health = 200;
    }

    public override void OnDestroy()
    {
    }
}

Example code of Factory:

public class ObjectFactory : IObjectFactory
{
    public Object GetObject(char mapCharacter)
    {
        switch (mapCharacter)
        {
            case 'B':
                return new Box();
            case 'T':
                return new Tree();
            case 'W':
                return new Wall();
            case 'G':
                return new Grass();
            default:
                return null;
        }
    }
}

My idea was using Reflection get the Model of each class inherted from Object and somehow return that class, but that seems poor code

Upvotes: 1

Views: 405

Answers (3)

rsangin
rsangin

Reputation: 498

You can use this code sample. There is a class by name of EnhancedShapeFactory and it uses reflection.

Upvotes: 0

StepUp
StepUp

Reputation: 38094

It is worth to take a look Activator.CreateInstance method.

If a map has full name of class, then it is possible to create an instance like this:

public class InstanceHelper
{
    public static object Get(string fullyQualifiedName)
    {
        Type t = Type.GetType(fullyQualifiedName);
        return Activator.CreateInstance(t);
    }
}

So the above code can be called like this:

Box box = InstanceHelper.Get("Box") as Box;

Upvotes: 0

Guru Stron
Guru Stron

Reputation: 142048

There are pros and cons of going with reflection (personally I would not go this way in general case) but with current code you can improve it a bit and reduce the boilerplate by "converting" switch to dictionary:

public class ObjectFactory 
{
    private static readonly Dictionary<char, Func<MyObject>> _objectFactory = new Dictionary<char, Func<MyObject>>()
    {
        { 'B', () => new Box() },
        // ...
    };

    public Object GetObject(char mapCharacter)
    {
        if(_objectFactory.TryGetValue(mapCharacter, out var factory))
        {
            return factory();
        }

        return null;
    }
}

If you will decide that adding items to dictionary every time is to much - I would recommend to look into source generators, if this approach is to much - do not forget to "cache" the reflection.

Upvotes: 2

Related Questions