Как реализовать эту иерархию классов C # - PullRequest
0 голосов
/ 02 февраля 2011

То, что я хочу сделать, действительно просто.У меня есть класс, который обрабатывает выполнение моей базы данных под названием clsSQLInterface.Этот класс содержит статическую функцию с именем bool isSQLSafe, которая будет возвращать false, если SQL, отправляемый на выполнение, считается опасным.Это одна из причин, по которой я могу отфильтровывать любые злонамеренные действия.

Теперь другая часть моей программы должна иметь возможность выполнять такие действия, как UPDATE, DELETE и т. Д.думал, что я унаследую класс clsSQLInterface и переопределю функцию isSQLSafe чем-то, что всегда возвращает true.

Это не вопрос безопасности базы данных, кстати!

Хорошо, я сделал это следующим образом ...

public class clsSQLInterface //Code not shown, just definitions
{
  private static string connectionString(string sKey){...}

  public static bool isSQLSafe(string sSQL){...}

  public static DataTable executeSQLText(string sSQL, string sConnectionKey){...}

  public static DataTable executeGenericQuery(clsGenericSQL query,string sDBKey){...}
}

И главный класс ..

public class clsSQLInterface_unsafe : clsSQLInterface
{
    public clsSQLInterface_unsafe()
    {   
    }

    public new static bool isSQLSafe(string sSQL) //overriding the base method
    { return true; }
}

Хорошо.Проблема этого подхода заключается в том, что isSQLSafe вызывается из методов executeSQLText и executeGenericQuery.Я хочу, чтобы эти методы вызывали переопределенный isSQLSafe, который всегда возвращает true.Однако они этого не делают.Они вызывают базовую реализацию.

Должен ли я также переопределять каждый метод, который вызывает isSQLSafe? Это кажется пустой тратой кода.

Конечно, когда я наследую класс, я фактически «копирую» все базовые методы, и они должны вести себя так, как будто они теперь являются частью clsSQLInterface_unsafe?

Ответы [ 2 ]

6 голосов
/ 02 февраля 2011

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

EDIT : модификатор new static просто сообщает компилятору, что вы намереваетесь скрыть метод базового класса (попробуйте удалить его и увидеть предупреждение, которое вы получите), но это ничего не отменяет .

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

P.S: взгляните на лучшее объяснение, что такое виртуальная таблица здесь: http://en.wikipedia.org/wiki/Virtual_method_table

3 голосов
/ 02 февраля 2011

Проблемы возникают из-за модификатора static.

Вы можете пересмотреть рефакторинг своего кода, используя, например, что-то вроде этого:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace ConsoleApplication1
    {
        public abstract class BaseSqlInterface
        {
            protected abstract bool IsSafe(string instruction);

            public void Execute(string sqlStatement)
            {
                if (IsSafe(sqlStatement))
                {
                    // run the sql command
                }
                else
                {
                    throw new Exception("You're evil");
                }
            }
        }

        public class SqlInterfaceSafe : BaseSqlInterface
        {
            public override bool IsSafe(string instruction)
            {
                return instruction.Contains("I'm not evil, I promise");
            }
        }
        public class SqlInterfaceUnsafe : BaseSqlInterface
        {
            public override  bool IsSafe(string instruction)
            {
                return true;
            }
        }


        public static class SqlInterfaceFactory
        {
            public static BaseSqlInterface GetInstance()
            {
                // return the actual object using IOC, switch, ... whichever method you want
                return DateTime.Now.Day % 2 == 0 ? (BaseSqlInterface)new SqlInterfaceSafe() : new SqlInterfaceUnsafe();
            }
        }
    }
...