具有通用结构的C#类设计

时间:2011-01-04 09:41:31

标签: c# generics class-design object-design

这可能是一个简单的问题,但我的头脑却拒绝将其包裹起来,因此在这种情况下外部视图总是有用的!

我需要设计一个对象层次结构来为患者实现参数注册。这将在某个日期进行,并收集关于患者的许多不同参数(血压,心率等)。这些参数注册的值可以是不同的类型,例如字符串,整数,浮点数甚至guid(用于查找列表)。

所以我们有:

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;}
}

这确实有点简单,但现在我想知道,因为ParameterRegistration中的IList指向 abstract ParameterRegistrationValue对象,我怎样才能获得实际值(因为它的存储在子对象上)?

也许整个通用的东西确实不是最终的方式:s

4 个答案:

答案 0 :(得分:4)

如果你不知道最后一组参数和每个参数的相应类型,那么泛型可能无济于事 - 使用 object 作为参数值类型。

此外,遍历参数列表将会非常痛苦,因为您必须检查每个项目的类型,以确定如何处理该值。

你想用仿制药做什么?是的,它们很酷(而且装箱/取消装箱可能不是最好的主意),但在某些情况下你可能想要使用对象(为了简单和灵活性)。

- 帕维尔

答案 1 :(得分:2)

您可能想要介绍的是RegistrationValue<T>的抽象基类,它不是通用的,因此您的ParameterRegistrationValue类可以包含非泛型引用,而无需了解所涉及的类型。或者,也可以使ParameterRegistrationValue泛型,然后为它添加非泛型基类(以便ParameterRegistration中的值列表可以是不同类型。

第一种方式:

public abstract class RegistrationValue
{
}

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

  public T Value { get; private set; }
}

现在你的代码应该编译。


一旦你有了一个非泛型基类,我也会将不依赖于泛型类型参数的泛型类的任何成员移动到这个基类中。这个示例中没有任何内容,但如果我们将ParameterRegistrationValue修改为通用,我会将Parameter移到非泛型基类中(因为它不依赖于RegistrationValue)的类型参数

答案 2 :(得分:0)

可能是,您应该使用公共RegistrationValue RegistrationValue,其中T - 是类型,在泛型中使用。例如,T - 是String或其他类或结构。

或者你应该将类ParameterRegistrationValue作为泛型,在RegistrationValue字段中使用泛型参数。

答案 3 :(得分:0)

我相信您希望拥有不同RegistrationValue s派生类的实例集合,并能够迭代它并为每个元素设置不同的类型。那是相当不可能的。

你仍然需要将每个元素强制转换为你知道的类型,因为迭代集合将返回对你的基类型的引用(ParameterRegistrationValue - 这个由IList类型参数指定的引用) 。因此,迭代非通用object列表不会产生任何真正的区别。

如果您可以安全地为每个参数执行转换(您知道所有类型),您可能根本不需要这样的集合 - 最好有一个类将所有参数封装在一个中类型,以便您可以使用强类型调用它,使用IntelliSense等,如下所示:

public class ParameterRegistration
{
  public DateTime RegistrationDate { get; set; }
  public PatientData PatientData { get; set; }
  public Guid Identifier { get; set; }
  // ...
}