2009-04-06 2 views
3

Мы работаем над приложением Windows, которое периодически запускает операции, которые могут занять некоторое время. Мы получили представление о том, что эти операции выполняются на BackgroundWorker и записывают быстрый WinForm для каждой операции, где вы передаете форме необходимые параметры, форма соединяется с BackgroundWorker и вызывает вызов функции, и форма отображает результат (индикатор выполнения перемещается, текст заполняется обновлениями и т. д.).Генерирование рабочего стола .NET

Теперь, очевидно, эта форма является очень куки-резаком. Единственная часть, которая действительно отличается между копиями формы, - это какой метод вызывается на каком объекте. Итак, что мы хотели бы сделать, это сделать его общим, чтобы мы могли принять форму, передать объект (или null для статических вызовов?), Имя функции и массив параметров, и заставить ее просто «идти», оттуда. Мы смогли сделать это с помощью Reflection. То, что нам не нравится в этом случае, - это отсутствие сильной типизации; такие вещи, как неправильное написание вызова метода, попадают во время выполнения, а не во время компиляции. Есть ли что-нибудь доступное сейчас, которое может сделать это более элегантным и надежным? Я слышал о людях, которые говорили о вещах, таких как Делегаты и Деревья выражений; но я не уверен, что первое применимо и все еще немного в темноте о последнем.

ответ

6

Сделайте общую форму и передайте ей делегат, указывающий на способ, которым он должен работать на BackgroundWorker, было бы разумным решением.

Возможно, конструктор формы может принять в качестве аргумента общий делегат (действие может быть хорошей идеей) и передать в конструкторе лямбда-выражение, которое соответствует сигнатуре Action). Затем, для действия foreach, вам нужно будет указать только подходящее выражение лямбда.

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

+0

Как я понял, мне нужно было создать новый делегат для каждого метода, который в конечном итоге может быть вызван таким образом? – GWLlosa

+0

@GWLIosa. Я попытался немного расширить ответ, чтобы уточнить это. Вам не нужно указывать явный тип делегата для каждого метода. – driis

3

Возможно, вы захотите также проверить функции Лямбда. Я использую их специально, когда я работаю с Generics. В противном случае делегаты, вероятно, будут работать нормально.

2

Одна вещь, которую вы могли бы сделать, это создать несколько различных методов (один для методов без каких-либо аргументов, один для методов с одним аргументом, и т.д.), как это:

public static void DisplayForm(Action action) { 
    DisplayFormUsingInvoke(action); 
} 

public static void DisplayForm<T>(Action<T> action, T param) { 
    DisplayFormUsingInvoke(action, param); 
} 

public static void DisplayForm<T,U>(Action<T,U> action, T param1, U param2) { 
    DisplayFormUsingInvoke(action, param1, param2); 
} 

... 

Затем, вы можете иметь частный метод который фактически делает работу, так же, как ваш текущий метод, но не подвергается код клиента:

private static void DisplayFormUsingInvoke(Delegate d, params object[] parms) { 
    // Edit this code to run it on the background thread, report progress, etc. 
    d.DynamicInvoke(parms); 
} 

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

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