从我的C# 4.0
代码,我想对Sybase
和MSSQL
执行一些查询。正在使用(或将要使用)的数据库将只在运行时决定/知道。
我使用AseCommand
和SqlCommand
分别为Sybase和SQL。
我决定创建这样的通用方法:
private Department ExecuteCommand<T>(T databaseCommand) where T : class
{
Department department = new Department ();
dynamic command = databaseCommand;
using (dynamic databaseReader = command.ExecuteReader())
{
if (databaseReader.HasRows)
{
while (databaseReader.Read())
{
department.Employees.Add(this.CreateDepartmentInstance(databaseReader));
}
}
}
command.Connection.Dispose();
return department;
}
问题:
- 有比
dynamic
更好的选择吗? - 通常知道传递给泛型方法的参数类型的正确方法是什么? 当然,我可以为Sybase和SQL编写两个单独的方法。但是,当
dynamic
这样的东西可供使用时,为什么要这样做呢?您在这里不一定需要动态,您所需要的只是一个公共接口(在这个实例中它们都有):
private Department ExecuteCommand<T>(T databaseCommand) where T : IDbCommand
然而,在这个实例中,由于您没有对类型T
做任何特别有趣的事情(据我所知),因此以下方法签名就足够了:
private Department ExecuteCommand(IDbCommand databaseCommand)
一般来说,如果没有公共接口,我建议使用facade模式,并简单地将方法调用委托给实际实现上的等价对象。
看起来AseCommand
和SqlCommand
都实现了IDbCommand
,所以你只需要改变类型约束:
private Department ExecuteCommand<T>(T databaseCommand) where T : IDbCommand
{
Department department = new Department();
using (IDataReader databaseReader = databaseCommand.ExecuteReader())
{
if (databaseReader.HasRows)
{
while (databaseReader.Read())
{
department.Employees.Add(
this.CreateDepartmentInstance(databaseReader));
}
}
}
command.Connection.Dispose();
return department;
}
我想象你还需要改变CreateDepartmentInstance
来接受IDataReader
,如果它还没有。
虽然有钱。Okelly指出,看起来并没有真正的理由在这里使用泛型。
对#2的回答:
if (typeof(T) == typeof(object) ) {
// Check for IEnumerable
}
将对象替换为您想要检查的任何类型
在您的情况下,使用公共接口就可以了。
一般来说,如果你想知道一个对象的类型,你总是可以使用is
和as
-操作符。
private Department ExecuteCommand<T>(T databaseCommand) where T : class
{
Department department = new Department ();
var command = databaseCommand;
using (var databaseReader = command.ExecuteReader())
{
if ((databaseReader as IDataReader).HasRows)
{
while ((databaseReader as IDataReader).Read())
{
department.Employees.Add(this.CreateDepartmentInstance(databaseReader));
}
}
}
command.Connection.Dispose();
return department;
}