1

Below is my factory class:

public class BulkFactory<T>
{
    private BulkFactory() { }

    static readonly Dictionary<string, Func<T>> _dict
         = new Dictionary<string, Func<T>>();

    public static T Create(string id)
    {
        Func<T> constructor = null;
        if (_dict.TryGetValue(id, out constructor))
            return constructor();

        throw new ArgumentException("No type registered for this id");
    }

    public static void Register(string id, Func<T> ctor)
    {
        _dict.Add(id, ctor);
    }
}

And this is how I am registering various bulk job to this factory:

BulkFactory<IBulk>.Register("LCOUPD", () => new BAT_LCOUPD<BulkLCOUpdateRecord, BAT_LCOUPD_LOG>(bulkJobCode));
BulkFactory<IBulk>.Register("STBILL", () => new BAT_STBILL<BulkStartStopBillUpdateRecord, BAT_STBILL_LOG>(bulkJobCode));
BulkFactory<IBulk>.Register("PLANCH", () => new BAT_PLANCH<BulkPlanChangeUpdateRecord, BAT_PLANCH_LOG>(bulkJobCode));
BulkFactory<IBulk>.Register("CSCORE", () => new BAT_CSCORE<BulkCSCOREUpdateRecord, BAT_CSCORE_LOG>(bulkJobCode));
BulkFactory<IBulk>.Register("CUSTAQ", () => new BAT_CUSTAQ<CustomerAcquisitionTemplate, BAT_CUSTAQ_LOG>(bulkJobCode));

In order to follow Open Closed principal I want to store all these register entries into configuration file and wanted to load it back from configuration. So that whenever I add a new bulk job I need not to modify above lines of code.

Please suggest how can I achieve this.

Sergii Zhevzhyk
  • 4,074
  • 22
  • 28
Vipul
  • 1,563
  • 4
  • 22
  • 46

1 Answers1

2

Assuming you have a FactoryMethod array:

public sealed class FactoryMethod {
    public string Name { get; set; }
    public string Type { get; set; }
}

Which you somehow read from your configuration file where Name is class name you want to register (LCOUPD, STBILL and so on) and Type is in the format required by Type.GetType() for generic types:

TClass`2[TGenericType1, TGenericType2].

For example (assuming a fictional namespace Ns):

Ns.BAT_CUSTAQ`2[Ns.CustomerAcquisitionTemplate, Ns.BAT_CUSTAQ_LOG]

Then you may write this code:

foreach (var factoryMethod in factoryMethods) {
    BulkFactory<IBulk>.Register(factoryMethod.Name,
        (IBulk)Activator.CreateInstance(Type.GetType(factoryMethod.Type), bulkJobCode));
}

Note that I don't know exact type of your classes and prototype of your functions then you may need a cast here or there.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • I just realized that this implementation is utilizing reflection which may impact performance. Is there some way around without reflection? – Vipul Dec 06 '15 at 18:54
  • No, unless you make things terribly more complicate (for example precimpiling code). However...reflection impacts performance but will you ever notice during startup? – Adriano Repetti Dec 06 '15 at 19:54