返回泛型类型实例

本文关键字:实例 泛型类型 返回 | 更新日期: 2023-09-27 17:49:44

我编写了一个泛型类,并希望通过静态方法创建它的实例。问题是我不能创建对象的通用实例。我知道这听起来很混乱,最好是显示代码。

public class Parameter<T> : IParameter<T>
{
    public string Name { get; set; }
    public T Value { get; set; }
    public bool IsValid()
    {
        if (String.IsNullOrEmpty(Name))
            return false;
        return (typeof(T) == typeof(String)) ||
               typeof(T) == typeof(bool) ||
               typeof(T) == typeof(int) ||
               typeof(T) == typeof(double);
    }
    public XElement ToXml()
    {
        if (!IsValid())
            throw new InvalidParameterException();
        var xElement = new XElement("Parameter", Value,
                                    new XAttribute("Type", typeof (T)),
                                    new XAttribute("Name", Name));
        return xElement;
    }
    public static Parameter<T> FromXml(XElement xElement)
    {
        var sType = xElement.Attributes()
                    .Where(attribute => attribute.Name == "Type")
                    .Single().Name.ToString();
        var name = xElement.Attributes()
                                .Where(attribute => attribute.Name == "Name")
                                .Single().Name.ToString();
        var sValue = xElement.Value;//need to use this
        var typeVar = Type.GetType(sType);// and this to create proper instance of Parameter<T>
        //I need somehow set T equal to typeVar here and Set
        return new Parameter<T>() {Name = name};//this is wrong. 
        //I need return either Parameter<int> or Paramter<double> or Parameter<string> or Parameter<bool> 
        //basing on typeVar
    }
}

我不确定这是否可能…但看起来这是琐碎的对象设计要求。什么好主意吗?谢谢!

UPD:我正在使用。net 4.0。这有什么区别吗?:)

UPD2:现在看看这个问题,我发现这是一个愚蠢的问题。而且不可能返回这样的"通用"对象。

返回泛型类型实例

创建一个非泛型基类,并从中继承泛型类(它们可以具有相同的名称,只是泛型类型不同)。在非泛型基类上,在静态方法中创建泛型实例(它将非泛型基类作为结果返回)。然后,您可以将其强制转换为您期望的泛型类型。

public abstract class Parameter {
  public static Parameter FromXml(XElement xElement) {
    ...
  }
  public string Name { get; set; }
  public abstract XElement ToXml();
}
public class Parameter<T>: Parameter {
  public T Value { get; set; }
  public override XElement ToXml() {
    ...
  }
}

实际上没有其他方法可以做到这一点,因为在您的示例中,T的类型是在静态方法运行之前指定的。

问题是:T是在编译时计算的。编译器没有任何机会知道,你的'sType'将在运行时计算为哪种实际类型。此外,在编译后的程序集中,不再存在泛型。因此,为了在运行时根据只能在运行时求值的条件构造类型,无论如何都必须向编译器提供一个具体的类型进行编译。在某个地方,你可以在if中决定返回类型。

if (sType is String)
   return new Parameter<String>()
else if (sType is double)
   return new Parameter<double>()
...

可以放在工厂类中,也可以放在XElement类附近。例如,为了能够返回Parameter,您可以使用一个接口(或一个公共基类,就像在另一个答案中一样),它可以代表所有Parameter变体。这就是为什么解析Xml IMO的方法最好放在Parameter之外的原因。

而且,既然看起来您肯定会从XML中"反序列化",那么考虑使用一些反序列化功能;)

这对自定义类有效,但对值类型可能不起作用。看看这篇文章,看看堆类型是如何工作的。

根据SLaks的指示,这是不可能的。这样想,

Parameter<???> value = Parameter<???>.FromXml(...);

当它依赖于XmlElement的内容时,您将如何解决问号应该是什么?

您应该使用一个公共类,它既捕获Value作为对象,又公开类型信息。