Как я могу реализовать таблицу? - PullRequest
0 голосов
/ 18 февраля 2012

Предположим, вам нужно сохранить некоторые значения в таблице, состоящей из нескольких столбцов (например, реляционной базы данных): например, int для первого столбца, string для второго, DateTime длятретий и т. д.

Если один или несколько столбцов подобны первичному ключу, то мы можем использовать IDictionary, чей Key будет набором полей, которые действуют как первичный ключ.Остальные поля представляют Value.В этом случае я мог бы создать один или два класса / структуры.Например, если первичный ключ является просто существующим типом, нам нужно будет только создать класс / структуру, подобную следующей:

public class MyValue
{
    public int Field1;
    public double Field2;
    public string Field3;
}

Словарь может быть Dictionary<int, MyValue>, тогда как таблица может бытьследующее.

public class MyTable
{
    private Dictionary<int, MyValue> _table;
    ...
}

Очевидно, что в зависимости от предметной области могут быть диапазоны и / или правила действия для вышеуказанных полей: например, Field1 может быть положительным и т. д...

В качестве первой альтернативы я мог бы спроектировать класс MyValue, чтобы он выдавал некоторые исключения для выявления "нарушения правил".Но, возможно, этот подход может быть чрезмерным, особенно если класс MyValue используется только внутренне для MyTable: в этом случае я бы написал код, подобный следующему, и обработал бы ошибку достоверности в MyTable классе: то есть MyTableкласс проверяет поля данных перед вставкой их в словарь, поэтому MyValue будет "глупым" классом ...

namespace MyNamespace
{
    class MyValue
    {
        // only public fields
    }

    public class MyTable
    {
        private Dictionary<int, MyValue> _table;
        ...

        public void Add(int key, int field1, double field2, string field3)
        {
            // some code to check validity range for fields
            ...
        }
    }
}

Правильно ли это решение?Или мне следует избегать такого подхода?Должен ли я всегда определять класс / структуру полностью (обработка исключений, Equals, GetHashCode методы?

Ответы [ 2 ]

4 голосов
/ 18 февраля 2012

То, что вы сделали, выглядит чрезмерно сложным, хрупким и в конечном итоге приведет к кошмарам ремонтопригодности.

Я бы сказал, у вас есть два варианта.

Первый вариант : используйте DataTable.Он не должен быть подкреплен реальной базой данных, и вы можете определить его макет (включая определения столбцов) во время выполнения.

Второй вариант : Определить класс, который реализует вашу логику записи.Определите коллекцию для хранения этого класса.Используйте LINQ для «запроса» к коллекции того, что вам нужно.

Основное различие между этими двумя вариантами состоит в том, что DataTable очень ограничен в типе правил, которые вы можете использовать.Вариант 2, OTOH, позволяет построить именно то, что вы хотите.

2 голосов
/ 18 февраля 2012

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

Я бы также предложил несколько более гибкий подход. Определите интерфейс, который ваши записи таблицы должны реализовать

public interface IRecord<PK>
{
    PK ID { get; }
}

Записи должны иметь идентификатор, который будет использоваться в качестве первичного ключа. Мы используем общий тип первичного ключа PK.

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

public class MyValue : IRecord<int>
{
    private int _field1;
    public int Field1
    {
        get { return _field1; }
        set
        {
            if (value < 0 || value > 1000) {
                throw new ArgumentException("Value of 'Field1' must be between 0 and 1000");
            }
            _field1 = value;
        }
    }

    public double Field2;

    #region IRecord<int> Members

    public int ID { get { return Field1; } }

    #endregion
}

Как видите, он реализует IRecord<int> и возвращает Field1 как ID. Field1 проверяет значения, переданные ему. Если первичный ключ состоит из нескольких полей, вы можете использовать тип типа Tuple (.NET 4.0) в качестве типа первичного ключа. Как IRecord<Tuple<int,double>>.

Теперь вы можете определить общую таблицу

public class Table<T, PK>
    where T : IRecord<PK>
{
    private Dictionary<PK, T> _table = new Dictionary<PK, T>();

    public void Add(T item)
    {
        _table.Add(item.ID, item);
    }
}

Вы можете определить определенные таблицы следующим образом

public class MyTable : Table<MyValue, int>
{
}

UPDATE:

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

public interface IRecord<PK> {
    PK ID { get; }

    bool IsValid { get; }
    string[] Errors { get; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...