Интерфейс как возвращаемый тип свойства, когда базовый тип * может * отличаться? - PullRequest
4 голосов
/ 28 августа 2010

Извините за название.Я понимаю, что это не очень наглядно.: |

Вот моя проблема.У меня есть класс Table, который определяет различные свойства, найденные для таблицы базы данных.В этом объекте у меня также есть свойство с именем PrimaryKey.PrimaryKey может быть типа PrimaryKey (я знаю, сбивает с толку) или CompositeKey.Очевидно, первичный ключ из одного столбца состоит из одного столбца, в то время как составной ключ состоит из двух или более столбцов.

/// <summary>
/// Defines what primary keys are supported.
/// </summary>
public enum PrimaryKeyType
{
    /// <summary>
    /// Primary key consisting of one column.
    /// </summary>
    PrimaryKey,
    /// <summary>
    /// Primary key consisting of two or more columns.
    /// </summary>
    CompositeKey,
    /// <summary>
    /// Default primary key type.
    /// </summary>
    Default = PrimaryKey
}

/// <summary>
/// Defines a database table entity.
/// </summary>
public class Table
{
    public Table()
    {
        Columns = new List<Column>();
    }

    public string Name { get; set; }
    public string Owner { get; set; }
    public AbstractPrimaryKey (What must the type be) PrimaryKey { get; set; }
    public IList<Column> Columns { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

/// <summary>
/// Defines a database column entity;
/// </summary>
public class Column
{
    public string Name { get; set; }
    public bool IsPrimaryKey { get; set; }
    public string DataType { get; set; }
    public bool IsNullable { get; set; }
}

public interface IPrimaryKey
{
    PrimaryKeyType KeyType { get; }
}

public interface IPk : IPrimaryKey
{
    Column KeyColumn { get; set; }
}

public interface ICompositeKey : IPrimaryKey
{
    IList<Column> KeyColumns { get; set; }
}

public abstract class AbstractPrimaryKey
{
    public abstract PrimaryKeyType KeyType { get; }
}

/// <summary>
/// Defines a primary key entity.
/// </summary>
public class PrimaryKey : AbstractPrimaryKey, IPk
{
    public override PrimaryKeyType KeyType
    {
        get { return PrimaryKeyType.PrimaryKey; }
    }

    public Column KeyColumn { get; set; }
}

/// <summary>
/// Defines a composite key entity.
/// </summary>
public class CompositeKey : AbstractPrimaryKey, ICompositeKey
{
    public CompositeKey()
    {
        KeyColumns = new List<Column>();
    }

    public override PrimaryKeyType KeyType
    {
        get { return PrimaryKeyType.CompositeKey; }
    }

    public IList<Column> KeyColumns { get; set; }
}

Я пытаюсь сделать так, чтобы независимо от PrimaryKeyType доступ к конкретному объекту таблицыдаст мне доступ к свойству Columns из класса CompositeKey.

Как мне этого добиться?Если это невозможно, какие у меня есть альтернативы?Я понимаю, что мог бы просто добавить IList<Column> Columns к IPrimaryKey.Это, однако, кажется не очень правильным, если у меня есть один основной столбец (который я знаю, что факт всегда будет один) внутри списка.Это мой первый опыт, поэтому я уверен, что в этом дизайне есть возможности для улучшения.

Ответы [ 2 ]

3 голосов
/ 28 августа 2010

Можно добавить свойство KeyColumns к AbstractPrimaryKey, даже если PrimaryKey всегда будет иметь одно значение - по крайней мере, интерфейс будет однородным.В ADO.NET DataTable.PrimaryKey - это массив DataColumn с (хотя современные руководящие указания предписывают, что это должен быть IList или класс коллекции).

Альтернативой может бытьоставьте все как есть, а затем отметьте PrimaryKeyType и приведите к CompositeKey при необходимости.Это имеет смысл, только если вам нужно провести различие в одном месте.

1 голос
/ 28 августа 2010

Если абстракция равна IPrimaryKey, то я думаю, что целесообразно иметь коллекцию столбцов, потому что когда вы работаете с этой абстракцией, вы не будете знать, что существует только один столбец. Все, что вы делаете полиморфно, должно предполагать, что PrimaryKey состоит из нуля или более столбцов (или «нуля или 1 или более столбцов»).

Для удобства вы можете добавить свойство Column к PrimaryKey.

...