Как я могу реорганизовать несколько подобных методов в один метод? - PullRequest
0 голосов
/ 14 апреля 2009

Предположим, у меня есть несколько связанных классов, у всех есть такой метод:

protected override OnExecute()
{
    this.constructorParm.BoolProperty = !this.constructorParm.BoolProperty;
}

Тип constructorParm может измениться (это также может быть static Setting), и определенное свойство обязательно изменится, но тип свойства всегда будет bool.

Предположим далее, что я решил, что глупо иметь 8 разных классов, которые все делают одно и то же на уровне реализации - переключают значение bool. Особенно, когда они все также связаны на семантическом уровне (все они происходят от одного и того же Command абстрактного базового класса, отсюда и OnExecute()).

Как мне параметризовать свойство, которое я хочу переключать, без параметризации самой операции переключения? Например, я знаю, что могу сделать что-то вроде этого (без компиляции):

internal class CommandX
{
    Action doExecute = null;
    public CommandX(Action executeAction) { this.doExecute = executeAction; }
    protected override OnExecute() { this.doExecute(); }
}

// elsewhere
var b = new CommandX(() => {target.BoolProperty = !target.BoolProperty;});

но как я могу зафиксировать переключающее поведение в классе, все еще принимая свойство записи в качестве параметра? (Если я передам переключение в качестве параметра, то я просто создаю слишком сложный делегат.)

(Я не могу просто передать свойство в b / c bool - это тип значения, поэтому я бы просто переключил копию. Я не могу передать его по ссылке, конечно, b / c Свойства не могут быть переданы по ссылке. Я чувствую, что должно быть что-то глупое и очевидное, что я просто действительно скучаю здесь. :))

Context

Причина, по которой я делаю такую ​​простую вещь косвенным образом, на самом деле связана с использованием шаблона GoF Command в winforms. Основные функциональные возможности Command являются более сложными, но это небольшое подмножество Command s по существу просто переключает свойство, которое будет вызывать события PropertyChanged в других местах. Вместо того, чтобы собирать все эти команды в отдельные классы, я хотел сложить их в один, потому что они такие простые.

Ответы [ 3 ]

2 голосов
/ 14 апреля 2009

Вы можете использовать Reflection, чтобы выбрать, какое свойство переключать, используя PropertyInfo class:

string propertyName = "BoolProperty";
Foo myFoo = new Foo();
Type myFooType = myFoo.GetType();
PropertyInfo prop = myFooType.GetProperty(propertyName);
prop.SetValue(myFoo, !((bool)prop.GetValue(myFoo, null)), null);

Вам нужно только сохранить имя свойства, которое вы хотите переключить.

Однако это имеет смысл, только если «переключение свойства» делает явной частью вашего дизайна. В противном случае это было бы определенно излишним для чего-то такого базового, когда «легким» решением является просто обычное переключение свойства.

0 голосов
/ 14 апреля 2009

Несколько хороших ответов здесь

Боюсь, я не эксперт ни по одному из них. Но я думаю, что ситуации похожи.

Можете ли вы изменить общий функционал этих двух методов?

0 голосов
/ 14 апреля 2009

Возможно, вы могли бы использовать отражение, чтобы указать, какое свойство изменить, но если количество вариантов ограничено (вы упомянули, что существует 8 классов), я бы порекомендовал вам использовать оператор switch и иметь перечисление в конструктор класса.

internal enum PropertyOption { Prop1, Prop2 }

internal class Bar {
  PropertyOptiion prop;
  public Bar(PropertyOption prop) {
    this.prop = prop;
  }
  public override OnFoo() {
    switch (prop) {
      case PropertyOption.Prop1:
        this.prop1 = !this.prop1;
        break;
      case PropertyOption.Prop2:
        this.prop2 = !this.prop2;
        break;
    }
  }
}
...