在另一个方法中将一个方法作为参数传递

3
我希望通过将一个方法作为参数传递来消除程序中的重复代码。这是我想要实现的功能:
 private void sqlQuery(Method sqlMethod)
{
    conn.ConnectionString = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
    try
    {
        //open SQL connection
        conn.Open();
        sqlMethod();
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.Write(ex.ToString());
    }
    finally
    {
        conn.Close();
    }
}

使用:

private void insertTemplate()
{
    //create SQL command
    SqlCommand insertTemplate = new SqlCommand("INSERT INTO [SavedDescriptionTemplates] (SavedDescription, UserId, CreatedDate) VALUES (@descriptionParam, @userIdParam, @createdDateParam)", conn);
    //create and assign parameters
    insertTemplate.Parameters.AddWithValue("@descriptionParam", descriptionInput.Text);
    insertTemplate.Parameters.AddWithValue("@userIdParam", Int32.Parse(userNameDropDown.SelectedItem.Value));
    insertTemplate.Parameters.AddWithValue("@createdDateParam", DateTime.Now);
    //execute command and retrieve primary key from the above insert and assign to variable
    insertTemplate.ExecuteNonQuery();
}

调用的语句应该是:
sqlQuery(insertTemplate());

这个可能吗?

除了重复的问题,我们还有可用的Action - musefan
1
请考虑将您的数据库代码包装在 using 块中,例如:using (SqlConnection connection = new SqlConnection(connectionString)){...} - DOK
1
注意,最好将连接对象定义为 sqlQuery 的本地变量,并将其作为参数传递给委托,而不是将其作为实例字段并使其他方法引用一个它们不知道是否打开的连接。然后,您需要使用 Action<SqlConnection> 委托,而不是 Action,并将连接作为参数传递给 insertTemplate。这可以确保您可以访问连接的任何位置都知道它是打开的。也可以与 DOK 的评论结合使用。 - Servy
7个回答

4
使用 Action 委托。
变更。
private void sqlQuery(Method sqlMethod)

转换为

private void sqlQuery(Action sqlMethod)

并且

sqlQuery(insertTemplate());

转化为

sqlQuery(insertTemplate);

1
是的,但略有不同...
试试这个:
sqlQuery(insertTemplate); // don't CALL the method, just name it

声明 sqlQuery 的方式如下:

private void sqlQuery(Action sqlMethod)

1
你可以通过委托来实现这一点。 例如,使用Action
private void sqlQuery(Action action)
{
    conn.ConnectionString = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
    try
    {
        //open SQL connection
        conn.Open();

        action();
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.Write(ex.ToString());
    }
    finally
    {
        conn.Close();
    }
}

1

请查看代理。在您的情况下,由于您的方法不需要参数,您可以使用内置的Action代理:

private void sqlQuery(Action sqlMethod)
{
    //...
}

sqlQuery(insertTemplate);

1

C#中的逻辑块作为委托传递。声明委托有几种方法 - 您可以定义自定义委托,也可以使用预定义类型之一:

  • 您可以使用Action<...>表示不返回值的委托,或者
  • 您可以使用Func<...,R>表示返回值的委托。

这是一种定义接受委托的函数的方法:

private void sqlQuery(Action<IDbConnection> sqlMethod) {
   ...
   sqlMethod(conn);
   ...
}

使用具有命名或匿名委托的 sqlQuery,可以内联定义、作为命名方法或作为 lambda 表达式调用它:
// Using some method that takes IDbConnection
sqlQuery(MySqlMethod);
// Using an anonymous delegate
sqlQuery((conn) => {
    ... // Do something with conn
});

1

是的。您需要使用委托、匿名函数或Lambda表达式。

这里有一个简单的例子:

public void SomeMethod(Action<string> passedMethod)
{
    passedMethod("some string");
}

public void Caller()
{
    SomeMethod(x => Console.WriteLine(x));
}

如果您运行“Caller”,它将输出“some string”。

0

委托是答案 -> Microsoft关于C#委托

public void delegate MyDelegate();

MyDelegate del = this.insertTemplate;

private void sqlQuery(MyDelegate sqlMethod)
{
 ...
 del();
 ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接