【发布时间】:2021-08-26 12:31:00
【问题描述】:
这是我的设置
首先,基类
public class TableBase
{
}
public class TableRepositoryBase
{
private BindingSource _bindingSourceOnForm;
public TableRepositoryBase(BindingSource bindingSource, string connectionString)
{
BindingSourceOnForm = bindingSource;
ConnectionString = connectionString;
SetupParameters();
}
protected string ConnectionString { get; set; }
protected Type TableType { get; set; }
protected BindingSource BindingSourceOnForm
{
get { return _bindingSourceOnForm; }
set { _bindingSourceOnForm = value;}
protected string SQLSelect { get; set; }
protected virtual void SetupParameters()
{ }
public virtual void FetchAll()
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
connection.Open();
BindingSourceOnForm.DataSource = connection.Query<TableType>(SQLSelect).ToList();
}
}
}
现在是我继承的类
public class TableUser : TableBase
{
public int UserID { get; set; }
public string UserFirst { get; set; }
public string UserLastname { get; set; }
}
public class TableRepositoryUser : TableRepositoryBase
{
public TableRepositoryUser(BindingSource bindingSource, string connectionString) : base(bindingSource, connectionString)
{ }
protected override void SetupParameters()
{
base.SetupParameters();
TableType = typeof(TableUser);
SQLSelect = "select UserID, UserFirst, UserLastname from tblUser";
}
}
现在的问题
在基类TableRepositoryBase 方法FetchAll() 中的以下代码行将无法编译:
BindingSourceOnForm.DataSource = connection.Query<TableType>(SQLSelect).ToList();
错误是
错误 CS0246 找不到类型或命名空间名称“TableType” (您是否缺少 using 指令或程序集引用?)
这将是因为query<> 正在寻找一个类型,虽然TableType 被声明为一个类型,但它可能会在这里将其视为一个变量。
我想要实现的是方法FetchAll可以完全由基类完成。
但是,我希望放在BindingSourceOnForm.DataSource 中的列表不是DapperRow 类型,而是在这种情况下为TableUser 类型。
我可以像这样在TableRepositoryUser 中重写这个方法
public override void FetchAll()
{
//base.FetchAll();
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
connection.Open();
BindingSourceOnForm.DataSource = connection.Query<TableUser>(SQLSelect).ToList();
}
}
这行得通,现在分配给BindingSourceOnForm.DataSource 的列表,如果类型为TableUser
但我想在基类中执行此代码,而不是在继承类中。
我怎样才能做到这一点?
编辑
我正在尝试调整我从@Flydog57 在 cmets 中获得的链接中的答案,但没有成功。
到目前为止我有这个
MethodInfo method = typeof(SqlConnection).GetMethod("Query");
MethodInfo generic = method.MakeGenericMethod(TableType);
BindingSourceOnForm.DataSource = generic.(SQLSelect).ToList();
我收到一个编译错误Identifier expected
我想这段代码根本没有意义,但我不明白如何使用MakeGenericMethod 来解决我的问题,如果可能的话。
所以这里的一些帮助将不胜感激
编辑 2
由于找不到解决办法,我现在使用这种低效的方法
public virtual void FetchAll()
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
connection.Open();
if (TableType == typeof(TableUser))
BindingSourceOnForm.DataSource = connection.Query<TableUser>(SQLSelect).ToList();
else if (TableType == typeof(TableTask))
BindingSourceOnForm.DataSource = connection.Query<TableTask>(SQLSelect).ToList();
}
}
仍然希望有更好的方法,因为这意味着每次从 RepositoryBase 继承新的存储库类时,我都必须回到这里并更改代码
【问题讨论】:
-
TableType是System.Type类型的变量,而不是类型。您不能直接使用变量调用泛型函数,只能使用类型。您必须使用反射来执行此操作 (MakeGenericFunction)。看这里:stackoverflow.com/questions/232535/… -
@Flydog57 感谢您提供此链接。但是,我无法从该问题的答案中为我的案例提取答案,这将解决我的问题。也许你可以写一个关于如何做到这一点的小样本,以便我可以在我的情况下使用它?
-
Dapper 可以使用
dynamic变量进行查询。也许这会对你有所帮助。但是,在某些时候,我会在您的未来看到工厂方法,除非您可以将您的表单绑定到List<dynamic>。值得一提的是,将转换放在派生类中几乎就是运行时多态性的全部意义所在。 -
@RobertHarvey 实际上你是对的。我应该在派生类中重写这个方法,让多态性完成它的工作。我想我在这里做了一些过度思考。
标签: c# winforms oop inheritance dapper