一个有2种返回类型的方法
本文关键字:2种 返回类型 方法 一个 | 更新日期: 2023-09-27 18:03:29
好的,我有3个类:教师, 学生和数据库。我想从数据库中读取数据,并把它放在Teacher或Student。所以我必须这样写:
public Teacher dbSelect(string Table="Teacher")
{
Table = char.ToUpper(Table[0]) + Table.Substring(1);
string query = "SELECT * FROM " + Table + ";";
return dbConnect(query, true);
}
但我必须有这个确切的方法学生返回:
public Student dbSelect(string Table="Student")
{
Table = char.ToUpper(Table[0]) + Table.Substring(1);
string query = "SELECT * FROM " + Table + ";";
return dbConnect(query, true);
}
现在我可以写每个在他们的ViewModel,但我想把他们在数据库类。有什么办法可以做到吗?
(我知道我可以在列表中返回它们,然后使用该列表,但只是想知道是否有一种方法!)
更新:我忘了把dbConnect放在这里,所以:
public List<Teacher> dbConnect(string query)
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
Teacher result = new Teacher(null, null, null, null, null, null, null, null);
// try
{
conn = new SQLiteConnection(db.db);
conn.Open();
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
}
// catch (Exception ex) { }
while (reader.Read())
{
Teacher temp = new Teacher(
reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString(),
reader[4].ToString(),
reader[5].ToString(),
reader[6].ToString(),
reader[7].ToString()
);
result.Items.Add(temp);
}
conn.Close();
return result.Items;
}
同样,对于Student返回:
public List<Student> dbConnect(string query)
{
...
}
答案:我有一个基类,当然想返回一个特定类型的列表,所以我使用@Jauch答案,但是返回列表。
这是一个关于如何做你想做的事情的想法,改编自我的代码:
public class BaseClass<T>
where T : new ()
{
protected List<object> list;
protected string query;
protected PropertyInfo[] fProperties;
protected Assembly fStoreAssembly;
public BaseClass()
{
list = new List<T>();
fStoreAssembly = Assembly.GetAssembly (typeof(T));
fProperties = typeof(T).GetProperties();
}
public void Read()
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
try
{
conn = new SQLiteConnection(db.db);
conn.Open();
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
StoreResults (reader);
conn.Close();
}
catch (Exception ex)
{
//deal with the exception here
}
}
//Store results walks through all the records returned and
//creates new instances of the store object and saves in the list,
//using reflection
protected void StoreResults (SQLiteDataReader reader)
{
if (fProperties == null)
throw new Exception ("Store type definition is missing");
while (reader.Read ())
{
object newStoreItem = fStoreAssembly.CreateInstance (typeof(T).FullName);
foreach (PropertyInfo pi in fProperties)
{
string lcName = pi.Name.ToLower ();
if (HasColumn(reader, lcName))
{
if (!reader.IsDBNull(reader.GetOrdinal(lcName)))
pi.SetValue(newStoreItem, reader[lcName], null);
}
}
list.Add (newStoreItem);
}
}
public bool HasColumn (SQLiteDataReader reader, string columnName)
{
foreach (DataRow row in reader.GetSchemaTable().Rows)
{
if (row ["ColumnName"].ToString () == columnName)
return true;
}
return false;
}
}
下面是如何创建Teacher和Student
public class TeacherInfo
{
//Properties for store info from database
}
public class Teacher : BaseClass<TeacherInfo>
{
public Teacher ()
: BaseClass()
{
query = "whatever you want here"
}
}
public class StudentInfo
{
//Properties for store info from database
}
public class Student : BaseClass<StudentInfo>
{
public Student ()
: BaseClass()
{
query = "whatever you want here";
}
}
由于Read例程是公共的,您可以从任何Teacher或Student实例调用Read。您甚至可以创建它们并将其存储为BaseClass,如果您不需要知道它是学生还是教师(用于常见例程等),则可以直接使用它
这不是一个广泛的例子,但只是一个方向的点,您可以使用它来使您的代码更通用。
您可以遵循使用接口返回值的语义,然后将返回类型强制转换为适当的类型,或者使用基类(接口更好,因为在实现接口时仍然可以将其他类扩展为基类)。实体接口可以按如下方式创建,
public interface SchoolEntity {
// Provide the similar properties as members of this interface.
}
然后你可以在你的Teacher
和Student
中实现这个接口。
public class Student : SchoolEntity { }
public class Teacher : SchoolEntity { }
最后,可以使用枚举使形参更清晰一些。它们在读取时会更清晰,而不是具有相同的参数类型。注意函数重载不考虑返回类型作为签名差异。
enum Entity { Teacher, Student }
然后您可以检查返回哪些数据。
public SchoolEntity dbSelect(Entity type)
{
switch(type) {
case Teacher:
var query = "SELECT * FROM Teacher";
return dbConnect(query, true);
// Rest of the cases.
}
}
请注意,您的SQL语句对SQL注入是开放的,任何人都可以删除表,或者执行可以传递给引擎的操作。
在列表中工作
使用列表不是一个好主意。毕竟,你会返回什么列表?是public List<Teacher> dbSelect
还是public List<Student> dbSelect
?这个问题的答案和解决方法是用一个相同的类型来备份这两种类型。
dbSelect
函数
请注意,您仍然只返回Teacher
类型,那么为什么您有一个学生呢?你一定要把它扔回去。事实上,如果我要开发这个。我必须使用dbSelect
函数将Entity
作为参数,以便将所有数据库请求和处理保存在单个函数中。
public List<Teacher> dbConnect(Entity type)
{
SQLiteConnection conn = null;
SQLiteCommand command = null;
SQLiteDataReader reader = null;
Teacher result = null; // Can be set to null.
// try
{
conn = new SQLiteConnection(db.db);
conn.Open();
string query;
// This way, leave the function to build the query.
if(type == Entity.Teacher) {
query = "SELECT * FROM Teacher";
} else {
query = "SELECT * FROM Student";
}
command = new SQLiteCommand(query, conn);
reader = command.ExecuteReader();
}
// catch (Exception ex) { }
while (reader.Read())
{
if(type == Entity.Teacher) {
Teacher temp = new Teacher(
reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString(),
reader[4].ToString(),
reader[5].ToString(),
reader[6].ToString(),
reader[7].ToString()
);
result.Items.Add(temp);
} else {
// Add the student.
}
}
conn.Close();
return result;
}
现在在这段代码中,您知道result
的类型是Teacher
。那里没有列表,这使得你的代码有点混乱。听我的建议:重写代码。
请浏览以下有用的连结:
显式接口实现
https://en.wikipedia.org/wiki/SQL_injection
签名和重载