2009-11-30 1 views
2

Я пишу абстрактный синтаксический анализатор файлов (C#), который расширяется двумя конкретными синтаксическими анализаторами. Оба должны выполнить несколько проверок. В настоящее время в абстрактном синтаксическом анализаторе существует метод проверки достоверности, который использует отражение для вызова всех методов с именем, начинающимся с «теста». Таким образом, добавление проверок так же просто, как добавление метода с именем, которое начинается с «теста».Отражение или динамическая диспетчеризация

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

public bool Validate() 
    { 
     bool combinedResult = true; 
     Type t = this.GetType(); 
     MethodInfo[] mInfos = t.GetMethods(); 

     foreach (MethodInfo m in mInfos) 
     { 
      if (m.Name.StartsWith("Check") && m.IsPublic) 
      { 
       combinedResult &= (bool)m.Invoke(this, null); 
      } 
     } 
     return combinedResult; 
    } 

ответ

0

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

Мне нравится ваш подход к быстрому и грязному материалу. Для производства качественного кода, я вижу следующие потенциальные проблемы с вашим подходом:

  • вы не проверяете для типов аргументов и возвращаемых типов, так что если вы или кто-то добавляет метод string CheckWithWrongReturnType, то ваш код брейки.
  • каждый раз, когда вы вызываете эту функцию, он вызывает GetMethods() и проходит через список. Это, вероятно, неэффективно. Возможно, лучше кэшировать этот список в массиве.

Чтобы избежать отражения, я бы создал делегат и чтобы каждый класс возвращал список делегатов.

delegate bool Validator(); 

bool F1() { return true; } 
bool F2() { return false; } 

List<Validator> validators = new List<Validator>(F1, F2); 

// затем в главном классе вы можете сделать это:

foreach(Validator v in validators) 
{ 
    combinedResult &= v(); 
} 
3

Вы должны использовать обычный ООП, а не отражение для этого. У вас есть абстрактный класс, представляющий абстрактный метод, например Validate. Каждому парсеру придется его реализовать. В Validate каждый синтаксический анализатор вызовет методы проверки переполнения для выполнения этой работы.

+0

Определенно лучше остаться со стандартной практикой объектно-ориентированного программирования. Отражение весьма полезно, но не так эффективно, как стандартные вызовы функций. – Zoidberg

+0

Кроме того, когда дело доходит до абстрактных деревьев синтаксиса (если вы используете их), посмотрите шаблон посетителя. – Zoidberg

2

Нет ничего плохого в том, что код работает ... пока кто-то не придет, чтобы его поддерживать. В частности, этот вид конвенции должен быть документирован достаточно тщательно, так как не сразу видно, как ваш класс будет делать то, что он делает.

(Как и в сторону, однако, с помощью отражения для этого будет довольно медленным.)

Наиболее очевидный способ может быть иметь абстрактный метод bool Validate() базы, реализуемый подклассов. Подклассы затем имеют, например,

public override bool Validate() 
{ 
    return TestFirst() && 
     TestSecond() && 
     TestThird(); 
} 

Хотя это выглядит громоздким, сразу видно, что происходит. Он также делает единичное тестирование Validate() ветерок.

Возможно также, что методы Testxxx() регистрируются в суперклассе в конструкторе, поэтому их вызывают автоматически - но это больше работает и, вероятно, менее ремонтопригодным.

Если вы действительно хотите сделать это с отражением, рассмотрите маркировку Testxxx() методов с атрибутами и отражающих их. Тогда ваш код остается читаемым.

 Смежные вопросы

  • Нет связанных вопросов^_^