I like to show variations of the vocabulary approach that others have already suggested. Based on this decision, you can do the following.
1 Define the base class:
public abstract class JobDoer { public abstract void DoJob(); }
2 Define an attribute for the design of workers.
public sealed class JobDoerAttribute : Attribute { JobDoerAttribute(string jobDoerId) { this.JobDoerId = new Guid(jobDoerId); } public Guid JobDoerId { get; private set; } }
3 Define the actual job classes that are decorated with this attribute. For instance:
[JobDoer("063EE2B2-3759-11DF-B738-49BB56D89593")] public sealed class SpecificJobDoer : JobDoer { public override void DoJob() {
4 Define a JobDoerFactory that allows you to retrieve instances of JobDoer by their identifier, as defined in the attribute:
public static class JobDoerFactory { static Dictionary<Guid, JobDoer> cache; static JobDoerFactory() {
In the BuildCache method BuildCache you can load instances of JobDoer using reflection.
private static Dictionary<Guid, JobDoer> BuildCache() {
I have not tested this code, so I donβt know if it compiles, but I used this mechanism in the project several years ago. Thus, it is easy to define new classes without having to connect them to some dictionary. This is done automatically at runtime.
This may sound a bit like overkill, but if you have the +2000 JobDoer classes, this can help you a lot.
Update: Please note: if you do not like the idea of JobDoerAttribute , you can implement it as an abstract property in the abstract JobDoer class. However, I found that using the attribute makes the code very explicit and expressive.