一种有两种返回类型的方法

时间:2016-08-21 14:16:35

标签: c# wpf methods

好的,我有3个课程:教师学生数据库。我想从数据库中读取数据并将其放在教师学生中。所以我必须写这样的东西:

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;
    }

学生确实存在但返回:

public List<Student> dbConnect(string query)
{
    ...
}  

答案:我有一个基础课程,当然希望返回一个特定类型的列表,所以我使用 @Jauch 回答,但返回列表

2 个答案:

答案 0 :(得分:0)

这是一个关于如何做你想做的事情的想法,改编自我的代码:

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;
    }
}

在这里你将如何创建教师和学生

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例程是公共的,您可以从任何教师或学生实例调用Read。 您甚至可以创建它们并存储为BaseClass并直接使用它,如果您不需要知道它是学生还是教师(对于常见的例程等)

这不是一个广泛的例子,但只是指向可以用来使代码更通用的方向。

答案 1 :(得分:0)

您可以遵循使用接口的语义来返回值,然后将返回类型转换为适当的语句,或者使用基类(接口会更好,因为您仍然可以在实现时将其他类扩展为基类接口)。实体接口可以创建如下,

public interface SchoolEntity { 
    // Provide the similar properties as members of this interface.
}

然后,您可以在TeacherStudent中实施此界面。

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。那里没有列表,这使你的代码有点混乱。听从我的建议:重新编写代码。

还请浏览以下有用链接:

Explicit Interface Implementation
https://en.wikipedia.org/wiki/SQL_injection
Signatures and overloading