【发布时间】:2020-08-31 20:07:21
【问题描述】:
我试图实现一个使用 System.Data.SQLite 功能的包装器,以便以良好的 OOP 方式摆脱重复代码。所以,我有以下通用方法:
public T SendSelectQuery<T>(string sql, Func<SQLiteDataReader, T> processResult) where T : IDBResult
{
try
{
using (var dbConnection = new SQLiteConnection("path"))
using (var cmd = new SQLiteCommand(sql, dbConnection))
{
dbConnection.Open();
cmd.CommandType = CommandType.Text;
using (SQLiteDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
return processResult(rdr);
}
}
}
catch (Exception ex)
{
return T ??????
}
}
T 是一个结果对象,即:
public interface IDBResult
{
bool Completed { get; set; }
string Exception { get; set; }
}
public abstract class CustomDBREsult : IDBResult
{
public bool Completed { get; set; }
public string Exception { get; set; }
public string Payload { get; set; }
public CustomDBREsult(bool Completed, string exception, string Payload)
{
this.Completed = Completed;
this.Exception = exception;
this.Payload = Payload;
}
}
public class SuccessCustomDBResult : CustomDBREsult
{
public SuccessCustomDBResult(string Payload) : base(true, string.Empty, Payload)
{
}
}
public class ErrorCustomDBResult : CustomDBREsult
{
public ErrorCustomDBResult() : base(false, "exception", string.Empty)
{
}
}
我想调用SendSelectQuery<CustomDBREsult>(...) 并获取CustomDBREsult child 的实例。
您可能已经注意到问题出现在catch 段中,我需要返回一个T 对象,但我无法实例化从CustomDBREsult 派生的适当错误对象。
我可以将SendSelectQuery<T> 的返回类型更改为IDBResult 并在catch 段中返回,如下所示:
public class DefaultDBError : IDBResult
{
public bool Completed { get; set; } = false;
public string Exception { get; set; } = "db exception";
}
但在这种情况下,我需要将SendSelectQuery<T> 的结果从IDBResult 转换为T。而且这似乎不是一个很好的做法。
IDBResult res = DBMethods.SendSelectQuery<CustomDBREsult>("sql query", processResult);
if (res is CustomDBREsult cdbres)
{
}
else if (res is DefaultDBError ddberror)
{
}
另一种选择是“提升”trycatch 块并在其中使用SendSelectQuery<T>,但我需要在使用SendSelectQuery<T> 的任何地方复制此块,并且仍将IDBResult 转换为@987654341 @。
如果 smn 能够理解我,将不胜感激您的 cmets。我想我的问题是对逻辑进行良好的抽象。
【问题讨论】:
-
您可能需要考虑使用 Dapper 为您处理样板 ADO.Net 代码。
-
我不会返回一些东西,而是创建一个派生自 IOException 之类的自定义类,然后抛出它
-
是的,这里的正确答案可能是使用 Dapper。 Dapper 已经为您完成了所有繁重的工作。
-
仔细考虑您是否真的想捕获该异常。根据我的经验,实际上应该捕获异常的地方很少。我会根据事情成功的情况来定制方法签名,并确定如果事情失败了,你可以在知道要做什么的链条上进一步捕获异常。
标签: c# design-patterns abstraction