2015-10-26 2 views
2

В настоящее время я реализую небольшое программное обеспечение, которое может читать данные из разных баз данных. Followin это код:Переопределить метод (тип возврата DBDataReader) и вернуть другой тип (SQLDBDataReader)

interface Fetch 
{ 
    Dictionary<string, DbDataReader> GetData(); 
} 

abstract class Conn : Fetch 
{ 
    abstract public void Connect(); 
    abstract public Dictionary<string, SqlDataReader> GetData(); 
} 

class SqlConn : Conn 
{ 
    public override void Connect() 
    { 
     _connection = new SqlConnection(_connectionString); 
     try 
     { 
      _connection.Open(); 
     } 
     catch (SqlException dbe) 
     { 
      throw dbe; 
     } 
    } 
    public override Dictionary<string, SqlDataReader> GetData() 
    { 
     using (_connection) 
     { 
      Dictionary<string, SqlDataReader> dataDictionary = new Dictionary<string, SqlDataReader>(); 
      _xmlDoc.Load("Queries.xml"); 
      XPathNavigator navigator = _xmlDoc.CreateNavigator(); 
      XPathNodeIterator iterator = navigator.Select("//query"); 
      while (iterator.MoveNext()) 
      { 
       _command = new SqlCommand(iterator.Current.ToString()); 
       _command.Connection = _connection; 
       _command.CommandText = iterator.Current.ToString(); 
       SqlDataReader reader = _command.ExecuteReader() as SqlDataReader; 

       dataDictionary.Add(iterator.Current.GetAttribute("name", ""), reader); 
      } 
      return dataDictionary; 
     } 
    } 
} 

class OraConn : Conn 
{ 
    public override void Connect() 
    { 
     _connection = new OracleConnection(_connectionString); 
    } 
    public override Dictionary<string, OracleDataReader> GetData() 
    { 
     using (_connection) 
     { 
      Dictionary<string, OracleDataReader> dataDictionary = new Dictionary<string, OracleDataReader>(); 
      _xmlDoc.Load("Queries.xml"); 
      XPathNavigator navigator = _xmlDoc.CreateNavigator(); 
      XPathNodeIterator iterator = navigator.Select("//query"); 
      while (iterator.MoveNext()) 
      { 
       _command = new OracleCommand(iterator.Current.ToString()); 
       _command.Connection = _connection; 
       _command.CommandText = iterator.Current.ToString(); 
       OracleDataReader reader = _command.ExecuteReader() as OracleDataReader; 

       dataDictionary.Add(iterator.Current.GetAttribute("name", ""), reader); 
      } 

      return dataDictionary; 
     } 
    } 
} 

Но моя проблема в том, возвращаемый тип, SqlDataReader и OraDataReader в производном классе. Это приводит к ошибке компиляции, что государства

«Ошибка 2„DashBoard.Connection.OraConn.GetData()“: тип возвращаемого значения должен быть„System.Collections.Generic.Dictionary“, чтобы соответствовать перекрытый элемент» DashBoard.Connection .Conn.GetData() '.

Как я могу решить эту проблему? Или есть другие способы реализовать эту функцию? Спасибо!

+1

Почему вы хотите изменить метод подписи на всех? – Dennis

+0

Потому что в функции я сделаю некоторые выписки с SqlCommand, SqlDataReader, а возвращаемое значение будет иметь тип Dictionary Gravity

ответ

2

Подпись метода должна оставаться неизменной, но до тех пор, пока ваши подклассы наследуют от DbDataReader, вы можете вернуть другие DbDataReader типы, такие как , и они скомпилируются.

, например:

abstract class DbDataReader 
{ 
    // ... 
} 

class SqlDataReader : DbDataReader 
{ 
} 

// ... 

class SqlConn : Conn 
{ 
    public override Dictionary<string, DbDataReader> GetData() 
    { 
     return new Dictionary<string, DbDataReader> 
     { 
      { "Key", new SqlDataReader() } 
     } 
    } 
} 
+0

Привет, Грег, спасибо! Я новичок в C#, и я не совсем понимаю код. Могу ли я использовать словарь dataDictionary = новый словарь () в функции GetData и использовать dataDictionary как возвращаемое значение ?? – Gravity

+0

Попробуйте, если компилятор говорит «нет», тогда вы не можете. Это связано с отклонениями, прочитайте это http://stackoverflow.com/questions/2184551/difference-between-covariance-contra-variance, но это может немного понять. –

1

Вы можете попробовать этот способ:

public interface IValue<T> { T GetValue(); } 
public class SomeClass : IValue<DbDataReader>, IValue<SqlDataReader> 
{ 
    DbDataReader IValue<DbDataReader>.GetValue() { return objDbDataReader; } 
    SqlDataReader IValue<SqlDataReader>.GetValue() { return objSqlDataReader; } 
}