Дизайн класса C # с общей структурой - PullRequest
1 голос
/ 04 января 2011

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

Мне нужно спроектировать иерархию объектов для реализации регистрации параметров для пациента. Это произойдет в определенный день и соберет ряд различных параметров о пациенте (артериальное давление, сердечный ритм и т. Д.). Значения этих регистраций параметров могут быть разных типов, таких как строки, целые числа, числа с плавающей запятой или даже направляющие (для списков поиска).

Итак, мы имеем:

public class ParameterRegistration
{
  public DateTime RegistrationDate { get; set; }
  public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}

public class ParameterRegistrationValue
{
  public Parameter Parameter { get; set; }
  public RegistrationValue RegistrationValue { get; set; }   // this needs to accomodate the different possible types of registrations!
}


 public class Parameter
  {
    // some general information about Parameters
  }

public class RegistrationValue<T>
{
  public RegistrationValue(T value)
  {
    Value = value;
  }

  public T Value { get; private set; }
}

ОБНОВЛЕНИЕ : Благодаря предложениям модель теперь трансформировалась в следующее:

public class ParameterRegistration
{
  public DateTime RegistrationDate { get; set; }
  public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}

public abstract class ParameterRegistrationValue() 
{
  public static ParameterRegistrationValue CreateParameterRegistrationValue(ParameterType type)
{
    switch(type)
    {
        case ParameterType.Integer:
            return new ParameterRegistrationValue<Int32>();
        case ParameterType.String:
                return new ParameterRegistrationValue<String>();
        case ParameterType.Guid:
            return new ParameterRegistrationValue<Guid>();
        default: throw new ArgumentOutOfRangeException("Invalid ParameterType: " + type);
    }
}
  public Parameter Parameter { get; set; }
}

public class ParameterRegistrationValue<T> : ParameterRegistrationValue
{
  public T RegistrationValue {get; set; }
}

public enum ParameterType
{
  Integer,
  Guid,
  String
}

public class Parameter
{
  public string ParameterName { get; set; }
  public ParameterType ParameterType { get; set;}
}

что на самом деле немного проще, но теперь мне интересно, так как IList в ParameterRegistration указывает на объект abstract ParameterRegistrationValue, как я смогу получить фактическое значение (так как оно хранится на подобъектах)?

Может быть, в общем и целом, в общем-то, это не совсем то, что нужно: s

Ответы [ 4 ]

4 голосов
/ 04 января 2011

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

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

Чего вы пытаетесь достичь с помощью дженериков? Да, они классные (и, вероятно, не самая лучшая идея - заниматься боксом / распаковкой), но в некоторых случаях вы можете использовать object (для простоты и гибкости).

- Павел

2 голосов
/ 04 января 2011

То, что вы, возможно, захотите ввести, - это абстрактный базовый класс для RegistrationValue<T>, который не является универсальным, так что ваш класс ParameterRegistrationValue может содержать неуниверсальную ссылку, не требуя знания соответствующего типа.В качестве альтернативы может быть целесообразно также сделать ParameterRegistrationValue универсальным, а затем вместо него добавить для него неуниверсальный базовый класс (чтобы список значений в ParameterRegistration мог иметь различные типы.

1stпуть:

public abstract class RegistrationValue
{
}

public class RegistrationValue<T> : RegistrationValue
{
  public RegistrationValue(T value)
  {
    Value = value;
  }

  public T Value { get; private set; }
}

А теперь ваш код должен скомпилироваться.


Если у вас есть базовый класс не универсального типа, я бы также переместил все члены универсального класса, которые нене зависят от параметров универсального типа в этом базовом классе. В этом примере их нет, но если бы мы вместо этого изменили ParameterRegistrationValue, чтобы он стал универсальным, я бы переместил Parameter в неуниверсальную базукласс (потому что он не зависит от параметра типа для RegistrationValue)

0 голосов
/ 04 января 2011

Я полагаю, что вы хотите иметь коллекцию экземпляров различных классов RegistrationValue s, производных от класса, и иметь возможность повторять их и иметь разные типы для каждого элемента.Это довольно невозможно.

Вам все равно нужно будет привести каждый элемент к типу, который вам известен, потому что итерация коллекции вернет ссылки на ваш базовый тип (ParameterRegistrationValue - этот тип указан параметром IList type).Так что это не будет иметь никакого реального значения от итерации по неуниверсальному списку object.

И если вы можете безопасно выполнить это приведение для каждого параметра (вы знаете все типы), вы, вероятно, не будетенужна такая сборка - лучше иметь класс, который инкапсулирует все параметры в один тип, так что вы можете вызывать его со строгими типами, с IntelliSense и т. д., например:

public class ParameterRegistration
{
  public DateTime RegistrationDate { get; set; }
  public PatientData PatientData { get; set; }
  public Guid Identifier { get; set; }
  // ...
}
0 голосов
/ 04 января 2011

Может быть, вам следует использовать public RegistrationValue RegistrationValue, где T - тип, использующий в общем. Например, T - это String или другой класс или структура.

Или вы должны сделать класс ParameterRegistrationValue как универсальный, чтобы использовать универсальный аргумент в поле RegistrationValue.

...