2010-04-14 2 views
1

У меня есть базовый базовый класс, из которого у меня много унаследованных классов. То, что я хотел бы сделать, - это статический член, который принимает строку, первый класс, который может анализировать строку (только один из унаследованных классов должен иметь возможность) и возвращать экземпляр унаследованного класса.Создайте унаследованный класс, используя статический метод из базового класса

Это то, что я сейчас делаю.

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#. Or am I hammering a nail in with a shoe when I should be using a hammer; любой лучший способ сделать эту фабрику класса будет оценен по достоинству.

ответ

1

C# не поддерживает статические интерфейсы, поэтому вы не можете определить статический метод строитель как

public interface ICommand 
{ 
    static ICommand CreateCommand(string command); 
} 

Я согласен с Кевином, что вам нужен шаблон Factory. Я сделаю еще один шаг и скажу, что вам нужен строитель для каждого типа команд. Как это

public interface ICommandBuilder 
{ 
    bool CanParse(string input); 
    ICommand Build(string input); 
} 

public interface ICommandBuilder<TCommand> : ICommandBuilder 
    where TCommand : ICommand 
{ 
    TCommand Build(string input); 
} 

Тогда ваш завод может принимать любую команду строку ввода, все запросы строителей, если они могут разобрать эту строку, и запустить сборки на одном, что может.

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); 
    } 
} 
+0

Отличная статья Джона Скита на статических интерфейсах. http://goo.gl/WPpV –

+0

, откуда взялся сговор? –

+0

Это pseduo-код, предполагающий, что вы используете инверсию контейнера управления ... Windsor, StructureMap и т. Д. Если вы не используете IoC, вам нужно будет найти все типы ICommandBuilder и создать их вручную. –

0

Что вы уклоняясь к является Factory Method:

http://www.dofactory.com/Patterns/PatternFactory.aspx

Вот ссылка, как это осуществить.

+0

Использование этого шаблона требует вызова другого класса для каждого типа подкласса. Я бы предпочел, если бы я мог сделать это с одной фабрикой, и это было бы достаточно умным, чтобы найти всех, кто наследует его, и выплевывать правильный тип без редактирования Epl2Command каждый раз, когда добавляется класс. –