2012-01-18 33 views
0

我想要做以下事情,但不能完全达到目的。我有一个datagridview窗体,我希望每次单击按钮时将源设置为不同的数据表。使用指定的参数创建一个方法集合

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

然后遍历该集合上的每个按钮点击:

​​

我意识到这可能需要某种类型的代表,如果可能的话,我通常可以将我的头围绕在他们身上,但这次不行。

我意识到这并不是最终会出现在生产代码中的东西,我只是用它来测试我的数据库调用,并且一旦完成就会将其埋没。我接受完全不同的方法的建议,但主要是寻找如何构建Foo来实现这个特定的目标。

+0

我假设这是一个客户端应用程序,基于缺少DataBind()调用,它将出现在Web应用程序中... – Tejs 2012-01-18 19:41:32

+0

ta.GetLineItemsByCustomerAndDate和ta.GetLineItemsByDocumentRange返回哪些数据类型?数据表?数据集? – 2012-01-18 19:43:58

+0

Tejs正确克里斯Shain DataTable – MalibuCusser 2012-01-18 19:50:31

回答

1

我假设ta.GetLineItemsByCustomerAndDateta.GetLineItemsByDocumentRange都返回DataTable;如果不是,只需用适当的类型替换以下任何DataTable事件。

您的代码存在的问题是您在将它们添加到列表之前正在执行上述方法,从而只将结果存储在列表中。相反,您需要稍后存储其执行的封装。为了实现后者,正如你所建议的,你需要使用代表。在C#3.5中,通过引入lambda expressions已明显简化了声明委托所需的语法;我建议你阅读它们。因此,我们首先声明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,但不接受任何参数。

+0

我正在思考这些行,但没有'List > Foo =新列表>()'我第一次和当那没用,来到这里。我知道lambda会起作用,只需要简化。 – MalibuCusser 2012-01-18 20:21:02

+0

它可能是'List >'的另一种方式,但是每次调用都必须提供'object []'参数。 – 2012-01-18 20:44:08

+0

@Olivier Jacot-Descombes谢谢,我扩展了你的观点。 – Douglas 2012-01-18 21:12:31

1

你假设你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]();  

时间的过滤器将被重新评估,回报现有客户。

相关问题