Reputation: 127603
I have a abstract base class that I have many inherited classes coming off of. What I would like to do is a static member takes in a string, the first class that can parse the string (only one of the inherited classes should be able to) and return a instance of the inherited class.
This is what i am currently doing.
public static Epl2Command GenerateCommandFromText(string command)
{
lock (GenerateCommandFromTextSyncRoot)
{
if (!Init)
{
Assembly a = Assembly.GetAssembly(typeof(Epl2Command));
Types = new List<Type>(a.GetTypes());
Types = Types.FindAll(b => b.IsSubclassOf(typeof(Epl2Command)));
Init = true;
}
}
Epl2Command ret = null;
foreach (Type t in Types)
{
MethodInfo method = t.GetMethod("GenerateCommand", BindingFlags.Static | BindingFlags.Public);
if (method != null)
ret = (Epl2Command)method.Invoke(null, new object[] { command });
if (ret != null)
break;
}
return ret;
}
I would like it so my code would check all inherited classes without having future programmers come back and edit this function when they add more inherited classes.
Is there a way I can force a inherited class to implement their own GenerateCommand(string)
?
public static abstract Epl2Command GenerateCommand(string command)
is not valid c#. Or am I hammering a nail in with a shoe when I should be using a hammer; any better way of doing this class factory would be appreciated.
Upvotes: 1
Views: 684
Reputation: 22404
C# does not support static interfaces, so you can't define a static builder method like
public interface ICommand
{
static ICommand CreateCommand(string command);
}
I agree with Kevin that you need a Factory pattern. I'll go a step further and say that you need a builder per command type, too. Like this
public interface ICommandBuilder
{
bool CanParse(string input);
ICommand Build(string input);
}
public interface ICommandBuilder<TCommand> : ICommandBuilder
where TCommand : ICommand
{
TCommand Build(string input);
}
Then your factory can accept any input command string, query all builders if they can parse that string, and run Build on the one that can.
public interface ICommandFactory
{
ICommand Build(string input);
}
public class CommandFactory
{
public ICommand Build(string input)
{
var builder = container.ResolveAll(typeof(ICommandBuilder))
.First(x => x.CanParse(input));
return builder.Build(input);
}
}
Upvotes: 1
Reputation: 115528
What you are eluding to is the Factory Method:
http://www.dofactory.com/Patterns/PatternFactory.aspx
Here is a link how to implement it.
Upvotes: 0