如何解决处理通用方法C#时不能做出适当的抽象
我试图实现一个包装器,以使用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
子实例。
您可能已经注意到问题发生在catch
段中,在该段中我需要返回一个T
对象,但是我无法实例化一个从CustomDBREsult
派生的approprite Error对象。
我可以将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)
{
}
另一种选择是“提起” try
catch
块并在其中使用SendSelectQuery<T>
,但是我需要在使用SendSelectQuery<T>
的任何地方复制此块,然后仍将IDBResult
转换为T
。
如果smn能够理解我,请感谢您的评论。我想我的问题是对逻辑进行了很好的抽象。
解决方法
我认为您在这里过度设计了问题。
首先,IDBResult接口实际上没有任何作用,因此您可以消除它。
让抽象类派生该类的成功和失败版本,它们自己似乎什么也没做,只是指出是失败还是成功,实际上并不能真正起到很多作用目的。
由于您要在原始Select中使用T作为有效负载,因此我会将您的自定义db结果更改为通用类型。
public class CustomDBREsult<T>
{
public bool Completed { get; set; }
public string Exception { get; set; }
public T Payload { get; set; }
public CustomDBREsult(bool Completed,string exception,T Payload)
{
this.Completed = Completed;
this.Exception = exception;
this.Payload = Payload;
}
}
尽管如此,除非这是您要挑战自己的一项练习,以提高您的设计技能,或类似的方法,否则那里有很多好的库已经为您完成了大部分工作,并且可以节省很多时间重新发明轮子。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。