【问题标题】:C# class design with Generic structure具有通用结构的 C# 类设计
【发布时间】:2011-01-04 09:41:31
【问题描述】:

这可能是一个简单的,但我的头脑拒绝围绕它,所以在这种情况下外部视图总是有用的!

我需要设计一个对象层次结构来为患者实现参数注册。这将在某个日期发生并收集有关患者的许多不同参数(血压、心率等)。这些参数注册的值可以是不同的类型,例如字符串、整数、浮点数甚至是 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

【问题讨论】:

  • 问题是什么,为什么要使用公共字段?
  • 你没有提到你的问题是什么。
  • 您在这里缺少什么?这不起作用吗?它在哪里/如何失败?
  • 你想要一个强类型的不同RegistrationValues派生类实例的集合吗?
  • 更新了示例以使用属性(只是简写)

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


【解决方案1】:

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

此外,遍历参数列表会很麻烦,因为您必须检查每个项目的类型才能确定如何处理该值。

你想用泛型实现什么?是的,它们很酷(并且进行装箱/拆箱可能不是最好的主意),但在某些情况下,您可能希望使用 object 代替(为了简单和灵活)。

-- 帕维尔

【讨论】:

  • 我确实知道每个参数的类型,这个信息将被存储在数据库中,以便检索。
  • 好的,在这种情况下,我建议使用非泛型类型作为集合类型(参数列表)和工厂模式根据实际参数值检索特定参数值类型。但是在这里使用泛型仍然不值得,恕我直言。
  • 我越是修改它,我就越开始同意你的观点,泛型也不是很理想。你会碰巧有一个你会为此实现的结构的例子吗?谢谢!
  • @Sam:我将更改 ParameterRegistration 类以包含一个名为 ParameterRegistrationValues 的 IList 类型的属性(而不是 IList)。 Parameter 类将只包含参数的名称和值(对象类型的属性)。
【解决方案2】:

您可能想要介绍的是RegistrationValue&lt;T&gt; 的抽象基类,它不是泛型的,因此您的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 移动到非泛型基类中(因为它不依赖于 @ 的类型参数987654328@)

【讨论】:

  • 它们肯定需要是不同类型的,因为参数注册可以包含许多不同类型的注册。
  • Damien,当您说“使 ParmaterRegistrationValue 通用”时,您的意思是代替 RegistrationValue 还是添加它?
  • @Sam - 我在想另外 - 这样它的 RegistrationValue 属性可以是特定类型。这取决于保留通用类型信息的层次结构有多高,以及我们绝对不想要它在什么级别(例如,当您想要保留此类值的列表时,它们将是不同的泛型)
  • 我明白你在说什么,但我不确定我是否理解它在这种情况下会带来的优势。
  • 我已经编辑了问题以更新模型,我想知道它是否真的可以将信息取出,因为无论如何你总是从集合中得到一个抽象类。 ..
【解决方案3】:

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

或者您应该将类​​ ParameterRegistrationValue 设为泛型,以便在字段 RegistrationValue 中使用泛型参数。

【讨论】:

    【解决方案4】:

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

    您仍然需要将每个元素转换为您知道的类型,因为迭代集合将返回对您的基本类型的引用(ParameterRegistrationValue - 这个由IList 类型参数指定)。因此,它与迭代非泛型 object 列表没有任何真正的区别。

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

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

    【讨论】:

    • 那么你会在 PatientData 对象中存储什么?谢谢。
    • 好吧,我不知道你的需求。难道你没有某种域对象可以代表你的Registration 的所有数据,封装所有可能的ParameterRegistrationValues?数据可能很多,但如果需要,您始终可以跳过不适用于传递null 的给定实例的数据。
    猜你喜欢
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多