Создание коллекции методов для вызова с указанными параметрами - PullRequest
0 голосов
/ 18 января 2012

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

DynamicsTableAccess ta;   
private void button1_Click(object sender, EventArgs e)
{
   //the DataSource for both calls will be a DataTable
   //first button click
   this.dataGridView1.DataSource = ta.GetLineItemsByCustomerAndDate(new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3});
   //second button click
   this.dataGridView1.DataSource = ta.GetLineItemsByDocumentRange(new object[] { "01254785", "01254885", 3 });
   //etc
}

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

Foo.Add(ta.GetLineItemsByCustomerAndDate(new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3}));
Foo.Add(ta.GetLineItemsByDocumentRange(new object[] { "01254785", "01254885", 3 }));

Затем повторяйте эту коллекцию при каждом нажатии кнопки:

int index = 0;
private void button1_Click(object sender, EventArgs e)
{
   this.dataGridView1.DataSource = Foo[index];
   index++;
}

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

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

Ответы [ 2 ]

1 голос
/ 18 января 2012

Вы предполагаете, что ваш GetLineItemsByDocumentRange метод определен так:

public DataTable GetLineItemsByDocumentRange(object[] filter)
{
}

Определите фильтры следующим образом:

List<Func<DataTable>> filters = new List<Func<DataTable>>();
filters.Add(() => ta.GetLineItemsByCustomerAndDate(new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3}));
filters.Add(() => ta.GetLineItemsByDocumentRange(new object[] { "01254785", "01254885", 3 }));

Каждый раз, когда вы звоните

this.dataGridView1.DataSource = filters[index]();    

Фильтр будет переоценен, возвращая текущих клиентов.

1 голос
/ 18 января 2012

Я предполагаю, что ta.GetLineItemsByCustomerAndDate и ta.GetLineItemsByDocumentRange оба возвращают DataTable;в противном случае просто замените все DataTable вхождения ниже на соответствующий тип.

Проблема с вашим кодом заключается в том, что вы выполняете указанные методы перед добавлением их в список, тем самым эффективно сохраняя их результат только всписок.Вместо этого вам нужно хранить инкапсуляцию их выполнения на более позднее время.Для достижения последнего, как вы предложили, вам нужно использовать делегатов.В C # 3.5 синтаксис, необходимый для объявления делегатов, был значительно упрощен благодаря введению лямбда-выражений ;Я бы посоветовал вам прочитать их.

Таким образом, мы сначала объявляем ваш список Foo (предположительно, как переменную экземпляра класса) для хранения делегатов (или функций), которые мы хотим выполнить позже.

List<Func<DataSet>> Foo = new List<Func<DataTable>>();

Затем мы можем добавить наши вызовы методов, инкапсулированные как анонимные функции, в список.Обратите внимание, что синтаксис () => заставляет любой оператор, который следует за ним, инкапсулироваться как анонимная функция.

Foo.Add(() => ta.GetLineItemsByCustomerAndDate(new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3}));
Foo.Add(() => ta.GetLineItemsByDocumentRange(new object[] { "01254785", "01254885", 3 }));

Наконец, нам просто нужно получить ссылку на одного из делегатов из списка - Foo[index] - и вызовите его, добавив (), обычно ассоциируемый с вызовами методов.

int index = 0;
private void button1_Click(object sender, EventArgs e)
{
    dt.Clear();
    this.dataGridView1.DataSource = Foo[index]();
    index++;
}

Редактировать : То, что вы пытались, дало бы вам что-то вроде этого:

List<Func<object[], DataTable>> Foo = new List<Func<object[], DataTable>>();
Foo.Add((objs) => ta.GetLineItemsByCustomerAndDate(objs));
Foo.Add((objs) => ta.GetLineItemsByDocumentRange(objs));

… или, более кратко, используя инициализаторы коллекции:

var Foo = new List<Func<object[], DataTable>>()
{
    (objs) => ta.GetLineItemsByCustomerAndDate(objs),
    (objs) => ta.GetLineItemsByDocumentRange(objs), 
};

… или, еще более кратко:

var Foo = new List<Func<object[], DataTable>>()
{
    ta.GetLineItemsByCustomerAndDate,
    ta.GetLineItemsByDocumentRange, 
};

Однако вам потребуется указать соответствующий аргументдля каждой анонимной функции для ее вызова.

this.dataGridView1.DataSource = Foo[0](new object[] { "REPT0000", DateTime.Parse("1/18/2012"), 3});
this.dataGridView1.DataSource = Foo[1](new object[] { "01254785", "01254885", 3 });

В этом случае это было бы нежелательно, поскольку вы пытались инкапсулировать весь вызов метода, включая заданные аргументы, как часть вашего анонимногофункция.Вы могли бы сказать, что исходная анонимная функция была более «полной», потому что ее тип был Func<DataTable>, что означает, что она имела тип возврата DataTable, но не принимала никаких аргументов.

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