我有一个负责所有数据库操作的类,通常它会调用存储过程。
我在班上创建了两个代表,一个负责肯定响应(例如服务器返回OK),第二个代表所有错误处理。
public delegate void Part1_Callback(string message);
public delegate void Part2_Callback(DataTable dt);
public delegate void Part3_Callback(DataTable dt, int x, int y);
public delegate void ErrorHandler(string message);
我将所有方法称为asynch,如上一个问题所示:C# asynch SQL inside singleton and delegates
当我需要我的委托返回不同类型的数据时,我遇到了问题。
例如,我的第一个方法返回String
,第二个方法返回DataTable
,第三个方法返回DataTable
和2 ints
。
现在,对于每个方法,我必须创建包含参数的类:
public class Part1_CommandAndCallback
{
public SqlCommand Sql;
public Part1_Callback Callback;
public ErrorHandler Error;
}
public class Part2_CommandAndCallback
{
public SqlCommand Sql;
public Part2_Callback Callback;
public ErrorHandler Error;
}
public class Part3_CommandAndCallback
{
public SqlCommand Sql;
public Part3_Callback Callback;
public ErrorHandler Error;
}
是否可以创建一个通用委托,以便我能够有一个响应委托和一个参数类?
通过这种方式,我可以更轻松地控制我的代码。
我发现有关codeproject的文章:http://www.codeproject.com/Articles/192027/Delegates-101-Part-III-Generic-Delegates但我不知道如何在我的情况下使用它:/
我应该像这样声明我的代表:
delegate void MyDelegate (params object[] params);
或:
public delegate void MyDelegate2<T>(T param1);
但这样我只能传递一个参数,我将无法为3个参数使用相同的委托。
哪种解决方案更好? 我想有一个通用委托,它能够采用不同类型的一到三个参数。
可以这样做吗?
修改
我会尝试展示我的情景:
在我的主窗体类中,我正在调用我的DB类:
private void form1_Enter(object sender, EventArgs e)
{
showStatus("Loading statistics...");
DB.Instance.Part1(part1_ok,ErrorHandler);
DB.Instance.Part2(part2_ok, ErrorHandler);
}
private void ErrorHandler(string msg)
{
hideStatus();
//viewStack1.InvokeIfRequired(c => { c.moveToFirst(); });
MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private void part1_ok(string msg)
{
MessageBox.Show(msg);
}
private void part2_ok(DataTable dt)
{
dataGridView1.InvokeIfRequired(c =>
{
c.DataSource = dt;
});
}
我的DB类看起来像这样:
public delegate void Part1_Callback(string message);
public delegate void Part2_Callback(DataTable dt);
public delegate void Part3_Callback(DataTable dt, int x, int y);
public delegate void ErrorHandler(string message);
public class Part1_CommandAndCallback
{
public SqlCommand Sql;
public Part1_Callback Callback;
public ErrorHandler Error;
}
public class Part2_CommandAndCallback
{
public SqlCommand Sql;
public Part2_Callback Callback;
public ErrorHandler Error;
}
public class Part3_CommandAndCallback
{
public SqlCommand Sql;
public Part3_Callback Callback;
public ErrorHandler Error;
}
class DB : SingletonBase<DB>
{
public static readonly string SqlConnectionString = @"Data Source=MyDB;Initial Catalog=Stats;Integrated Security=True;Asynchronous Processing=true;";
private DB()
{
}
public void Part1(Part1_Callback callback, ErrorHandler error)
{
SqlConnection conn = new SqlConnection(SqlConnectionString);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Part1";
try
{
conn.Open();
}
catch (Exception ex)
{
error(ex.ToString());
return;
}
Part1_CommandAndCallback ar = new Part1_CommandAndCallback() { Callback = callback, Error = error, Sql = cmd };
IAsyncResult result = cmd.BeginExecuteReader(new AsyncCallback(Part1_Handler), ar, CommandBehavior.CloseConnection);
}
private void Part1_Handler(IAsyncResult result)
{
string stats = string.Empty;
Part1_CommandAndCallback ar = (Part1_CommandAndCallback)result.AsyncState;
SqlDataReader dr;
if (result.IsCompleted)
{
dr = ar.Sql.EndExecuteReader(result);
}
else
dr = null;
while (dr.Read())
{
stats += dr[0].ToString() + Environment.NewLine;
}
dr.NextResult();
while (dr.Read())//problem is here
{
stats += dr[0].ToString() + " - " + dr[1].ToString() +Environment.NewLine;
}
dr.Close();
ar.Callback(stats);
}
public void Part2(Part2_Callback callback, ErrorHandler error)
{
SqlConnection conn = new SqlConnection(SqlConnectionString);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Part2";
try
{
conn.Open();
}
catch (Exception ex)
{
error(ex.ToString());
return;
}
Part2_CommandAndCallback ar = new Part2_CommandAndCallback() { Callback = callback, Error = error, Sql = cmd };
IAsyncResult result = cmd.BeginExecuteReader(new AsyncCallback(Part2_Handler), ar, CommandBehavior.CloseConnection);
}
private void Part2_Handler(IAsyncResult result)
{
DataTable dt = new DataTable();
Part2_CommandAndCallback ar = (Part2_CommandAndCallback)result.AsyncState;
SqlDataReader dr;
if (result.IsCompleted)
{
dr = ar.Sql.EndExecuteReader(result);
}
else
dr = null;
dt.Load(dr);
dr.Close();
ar.Callback(dt);
}
}
我的想法是同时以多种形式使用我的单例数据库控制器。因此,在第一种形式中,我会看到一些将自动刷新的统计数据,如果我愿意,那么第二种形式我将能够看到一些不同的统计数据,我将能够在按钮点击时刷新。
答案 0 :(得分:2)
答案 1 :(得分:1)
看起来你需要的是创建一个通用的CommandAndCallback
类:
public class CommandAndCallback<TCallback>
{
public SqlCommand Sql;
public TCallback Callback;
public ErrorHandler Error;
}
例如,您之前使用Part3_CommandAndCallback
的地方,如果您不想为每个部分创建委托类型,现在可以使用CommandAndCallback<Part3_Callback>
甚至CommandAndCallback<Action<DataTable, int, int>>
此外,通常不鼓励使用公共字段,因此您可以考虑将其更改为autoproperties:
public class CommandAndCallback<TCallback>
{
public SqlCommand Sql { get; set; }
public TCallback Callback { get; set; }
public ErrorHandler Error { get; set; }
}