Почему мой секундомер / таймер не сохраняет свою информацию во всех методах? - PullRequest
0 голосов
/ 07 ноября 2019

В настоящее время я работаю над проблемой, которая включает абстрактные классы и секундомеры. У меня есть два класса, SQL и Oracle. Они оба берут строку для кода соединения (этот материал на самом деле ничего не делает, но я пытаюсь сделать это немного реалистичным). Я хочу запустить секундомер, а затем остановить его другим способом - но интервал времени всегда говорит 00:00 ...

Правильно ли я обращаюсь к свойствам своего родительского класса?

Я попытался инициализировать свои секундомеры и временную шкалу в разных местах.

public class Program
    {
        public static void Main(string[] args)
        {
           // ConnectionManagement management = new ConnectionManagement();
           // management.SetUpOptions();


        }
    }

    public class ConnectionManagement
    {
        public void SetUpOptions()
        {
            while (true)
            {
                SqlConnection sqlGatherer = new SqlConnection("placeholder");
                OracleConnection oracleGatherer = new OracleConnection("placeholder");

                Console.WriteLine("1. Open an SQL connection.");
                Console.WriteLine("2. Close an SQL connection.");
                Console.WriteLine("3. Open an Oracle connection.");
                Console.WriteLine("4. Close an SQL connection.");
                string choice = Console.ReadLine();

                if (choice == "1")
                {
                    Console.WriteLine("Enter your connection string.");
                    string enteredConnectionString = Console.ReadLine();
                    sqlGatherer.ConnectionString = enteredConnectionString;
                    sqlGatherer.OpenConnection();
                }
                else if (choice == "2")
                {
                    sqlGatherer.CloseConnection();
                }
                else if (choice == "3")
                {
                    Console.WriteLine("Enter your connection string.");
                    string enteredConnectionString = Console.ReadLine();
                    oracleGatherer.ConnectionString = enteredConnectionString;
                    oracleGatherer.OpenConnection();
                }
                else if (choice == "4")
                {
                    oracleGatherer.CloseConnection();
                }
                else
                {
                    Console.WriteLine("That was not a valid option.");
                }
            }

        }
    }

    public abstract class DataBaseConnection
    {

        public string ConnectionString { get; set; }
        public TimeSpan Timeout { get; set; }
        public Stopwatch OracleStoppy { get; set; }
        public Stopwatch SqlStoppy { get; set; }
        public abstract void OpenConnection();
        public abstract void CloseConnection();

    }

    public class SqlConnection : DataBaseConnection
    {

        private bool CurrentConnection = false;

        public SqlConnection()
        {
            Timeout = new TimeSpan();
            SqlStoppy = new Stopwatch();
        }

        public SqlConnection(string connectionString)
        {

            Timeout = new TimeSpan();
            SqlStoppy = new Stopwatch();
            if (connectionString == null || String.IsNullOrWhiteSpace(connectionString))
            {
                throw new ArgumentException("Program has an invalid SQL connection string.");
            }
            else
            {
                this.ConnectionString = connectionString;
            }
        }

        public override void OpenConnection()
        {
            if (CurrentConnection == true)
            {
                throw new Exception("A connection has already been established.");
            }
            else
            {
                Console.WriteLine("SQL connection established.");
                SqlStoppy.Start();
                CurrentConnection = true;

            }

        }

        public override void CloseConnection()
        {
            if (CurrentConnection == false)
            {
                SqlStoppy.Stop();
                TimeSpan reportedTimeout = Timeout;
                Console.WriteLine("Connection closed. \nThe connection was active for {0}", reportedTimeout);
                SqlStoppy.Reset();
                CurrentConnection = false;

            }
            else
            {
                throw new Exception("There is no SQL connection to close.");
            }

        }
    }

    public class OracleConnection : DataBaseConnection
    {
        private bool CurrentConnection = false;

        public OracleConnection()
        {
            Timeout = new TimeSpan();
            OracleStoppy = new Stopwatch();
        }

        public OracleConnection(string connectionString)
        {
            Timeout = new TimeSpan();
            OracleStoppy = new Stopwatch();
            if (connectionString == null || String.IsNullOrWhiteSpace(connectionString))
            {
                throw new Exception("Program has an invalid Oracle connection string.");
            }
            else
            {
                this.ConnectionString = connectionString;
            }
        }
        public override void OpenConnection()
        {
            if (CurrentConnection == true)
            {
                throw new Exception("A connection has already been established.");
            }
            else
            {
                Console.WriteLine("Oracle connection established.");
                OracleStoppy.Start();
                CurrentConnection = true;
            }

        }

        public override void CloseConnection()
        {
            if (CurrentConnection == false)
            {
                throw new Exception("There is no Oracle connection to close.");
            }
            else
            {
                OracleStoppy.Stop();
                this.Timeout = OracleStoppy.Elapsed;
                Console.WriteLine("Connection closed. \nThe connection was active for {0}", Timeout);
                OracleStoppy.Reset();
                CurrentConnection = false;
            }

        }
    }

После закрытия открытого соединения метод должен напечатать, как долго оно было открыто, или продолжительность секундомера. Та же проблема произошла с моей переменной CurrentConnection, поэтому я поместил ее в качестве закрытой переменной в каждом классе. Но разве смысл в том, чтобы такой родительский класс имел общие свойства, с которыми могут взаимодействовать его дочерние классы?

1 Ответ

0 голосов
/ 07 ноября 2019

Проблема

Я вижу, что в оракуле у вас есть:

this.Timeout = OracleStoppy.Elapsed;
Console.WriteLine("Connection closed. \nThe connection was active for {0}", Timeout);

Но в sql:

TimeSpan reportedTimeout = Timeout;
Console.WriteLine("Connection closed. \nThe connection was active for {0}", reportedTimeout);

Это должно быть

this.Timeout = SqlStoppy.Elapsed;
Console.WriteLine("Connection closed. \nThe connection was active for {0}", Timeout);

Не правда ли?

Советы

Вы используете родительский класс, поэтому вам не нужны две секундомеры, только однанеобходимое, иначе наследование бесполезно, и вы повторяете код.

Вы должны рассмотреть также удалить некоторые сеттеры.

И переместить CurrentConnection, который повторяется, как защищенный.

Это должно быть:

public abstract class DataBaseConnection
{
    protected bool CurrentConnection;

    public string ConnectionString { get; }
    public TimeSpan Timeout { get; }
    public Stopwatch Stoppy { get; }
    public abstract void OpenConnection();
    public abstract void CloseConnection();

    public DataBaseConnection()
    {
      Timeout = new TimeSpan();
      Stoppy = new StopWatch();
    }
}

Также используйте шаблон вызова между конструкторами:

public OracleConnection()
{
  ...
}

public OracleConnection(string connectionString)
  : this()
{
  ...
}

Вы повторяете слишком много одного и того же кода, и вам действительно следует реорганизовать и улучшить абстрактные вещи.

Когда кодповторить вы можете:

  • создать один метод и вызывать его вместо повторяющегося кода.

  • иногда вы можете переместить его в родительский класс.

Когда переменные повторяются в дочерних классах, вы можете удалить их, чтобы иметь только одну в родительском классе.

Вы делаетечто играя с модификаторами, такими как public, private, protected, internal, abstract, virtual, override ...

Вы должны также переименовать некоторые переменные, чтобы быть болеенепротиворечиво и согласованно.

Правило состоит в том, что имя должно быть простым и точно указывать, что оно такое.

Например, Chrono может быть лучше, чем Stoppy, а также indexили indexRow лучше, чем i.

Так что здесь Duration или Elapsed может быть лучше, чем Timeout, что указывает на задержку остановки попытки подключения.

Такжепоскольку классы имеют имена Connection, вам не нужно указывать OpenConnection и CloseConnection: Open и Close достаточно.

Возможно, вы найдете это полезным:

Как мне улучшить свои знания в C #

Как выбрать модификатор частного и защищенного доступа

Что такое полиморфизм

...