返回泛型类型实例
本文关键字:实例 泛型类型 返回 | 更新日期: 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作为对象,又公开类型信息。