Создание экземпляра унаследованного класса с использованием статического метода из базового класса
У меня есть абстрактный базовый класс, из которого я получил много унаследованных классов. То, что я хотел бы сделать, это статический член, принимающий строку, первый класс, который может анализировать строку (должен уметь только один из унаследованных классов) и возвращать экземпляр унаследованного класса.
Это то, чем я сейчас занимаюсь.
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;
}
Я хотел бы, чтобы мой код проверял все унаследованные классы, не заставляя будущих программистов возвращаться и редактировать эту функцию, когда они добавляют больше унаследованных классов.
Есть ли способ заставить унаследованный класс реализовать свой собственный GenerateCommand(string)
?
public static abstract Epl2Command GenerateCommand(string command)
не является действительным C#. Или я забиваю гвоздь обувью, когда я должен использовать молоток; любой лучший способ сделать фабрику этого класса был бы оценен.
2 ответа
C# не поддерживает статические интерфейсы, поэтому вы не можете определить метод статического компоновщика, такой как
public interface ICommand
{
static ICommand CreateCommand(string command);
}
Я согласен с Кевином, что вам нужен шаблон Фабрики. Я сделаю еще один шаг и скажу, что вам также нужен сборщик для каждого типа команды. Как это
public interface ICommandBuilder
{
bool CanParse(string input);
ICommand Build(string input);
}
public interface ICommandBuilder<TCommand> : ICommandBuilder
where TCommand : ICommand
{
TCommand Build(string input);
}
Тогда ваша фабрика может принять любую входную командную строку, запросить у всех сборщиков, могут ли они проанализировать эту строку, и запустить Build на той, которая может.
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);
}
}
То, к чему вы обращаетесь - это фабричный метод:
http://www.dofactory.com/Patterns/PatternFactory.aspx
Вот ссылка, как это реализовать.