我写了一个泛型类,想要从静态方法创建它的实例。问题是我无法创建对象的通用实例。我知道这听起来很混乱,最好显示代码。
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 :现在看问题,我发现这是一个愚蠢的问题。并且不可能返回这样的“通用”对象。
答案 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作为对象捕获,也可以公开类型信息。