Какой правильный способ получения моих пользовательских классов перечисления по их значению? - PullRequest
2 голосов
/ 31 июля 2010

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

public abstract class Enumeration<X, Y> : IComparable where X : IComparable
{

    public Enumeration(X value, Y displayName) { }

    public Y DisplayName { get { return _displayName; } }
    public X Value { get { return _value; } }

}

И класс, который наследует его, будет:

public class JobType : Enumeration<string, string>
{
    public static JobType ChangeOver = new JobType("XY01", "Changeover");
    public static JobType Withdrawal = new JobType("XY02", "Withdrawal");
    public static JobType Installation = new JobType("XY03", "Installation");

    private JobType(string jobTypeId, string description)
        : base(jobTypeId, description) { }
}

Проблема, с которой я столкнулся, заключается в том, что я хочу разрешить эти значения из значения, возвращенного из базы данных в моем хранилище. Так что я за такой метод, как:

public static JobType Resolve(string jobTypeId) { return matchingJobType; }

Я начал писать метод resol для каждого класса перечисления, но должен быть лучший способ, чем дублировать один и тот же метод с инструкцией switch в каждом?

Я думал о добавлении свойства Dictionary<X, Enumeration<X, Y>> Cache; к базовому классу и добавлении в него класса из конструктора базового класса. Это также будет способствовать обеспечению уникальных ценностей. Проблема, с которой я столкнулся, заключается в том, что когда я получаю перечисление из словаря, оно имеет тип Enumeration<X, Y>, и я хочу его как JobType.

Таким образом, это означает, что необходимо добавить третий универсальный тип в класс Enumeration и иметь:

public static T Resolve(X value); // With the additional type
public static T Resolve<T>(X value); // Or without an additional type

Мне явно не нравится идея писать JobType.Resolve<JobType>(foo);, и я хочу просто JobType.Resolve(foo);, но это должно быть сделано с как можно меньшим количеством кода. То есть можно ли все это просто обработать из базового класса, не добавляя дополнительный универсальный тип?

Ответы [ 2 ]

3 голосов
/ 31 июля 2010

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

public abstract class Enumeration<TEnum, X, Y> : IComparable 
    where TEnum : Enumeration<TEnum, X, Y>
    where X : IComparable
{
    public static TEnum Resolve(X value) { /* your lookup here */ }

    // other members same as before; elided for clarity
}

Затем вы определите ваши конкретные классы следующим образом.

public class JobType : Enumeration<JobType, string, string>
{
    // other members same as before; elided for clarity
}

Теперь ваши типы будут совпадать, и для базового класса Resolve не требуется приведения.

JobType type = JobType.Resolve("XY01");

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

0 голосов
/ 31 июля 2010

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

public enum JobType
{
    ChangeOver,
    Withdrawal,
    Installation,
}

// Maybe inside some DAL-pattern/database parsing class:
var databaseToJobTypeMap = new Dictionary<string, JobType>()
{
    { "XY01", JobType.ChangeOver },
    // ...
};

Хранение кода синтаксического анализа вместе (возможно, с абстракцией интерфейса) дает вам возможность переключать парсеры, когда ваш формат хранения данных / потребности меняются, или если у вас есть несколько источников данных.

Если вам нужно проанализироватьфактические значения JobType (например, строка «ChangeOver» или целочисленное представление), затем вы можете использовать Enum.Parse / Enum.TryParse или приведение.

Реализация, которую вы имеете, кажется более негибкой,потому что он привязывает тип перечисления к одному стилю / представлению отображения словаря.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...