返回泛型类型的实例

时间:2011-04-12 16:28:25

标签: c# .net generics return-value

我写了一个泛型类,想要从静态方法创建它的实例。问题是我无法创建对象的通用实例。我知道这听起来很混乱,最好显示代码。

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 :现在看问题,我发现这是一个愚蠢的问题。并且不可能返回这样的“通用”对象。

4 个答案:

答案 0 :(得分:1)

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

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的类型。

答案 1 :(得分:1)

问题是:在编译时评估T.编译器没有任何机会知道你的'sType'将在运行时评估的实际类型。此外,在编译的程序集中,不再存在泛型。因此,为了在运行时构造一个类型,基于只能在运行时进行求值的条件,您必须将编译器作为一个具体的类型进行编译。所以在某个地方,你可以在if ... else级联中决定你的返回类型:

if (sType is String)
   return new Parameter<String>()

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

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

此外,由于看起来,您是XML的“反序列化”证明,请考虑使用一些解/序列化功能;)

答案 2 :(得分:0)

这适用于自定义类,但它可能不适用于值类型。看看This Post,了解这对堆类型的工作原理。

答案 3 :(得分:0)

如SLaks所示,这是不可能的。想一想,

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

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

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