[英]Returning Generic List from Generic method
我需要使用如下代码从通用列表返回一个genericList templateFields
,如下所示:
public interface TestData
{
string field { get; set; }
string fieldName { get; set; }
string type { get; set; }
}
private static IList<T> GETCG<T>(string test, string type) where T : Program.TestData
{
XmlNodeList extractNode = xdoc.SelectNodes(
@".//mediaInstances/mediaInstance/properties/templateFields/templateField", manager);
var nodees = new List<XmlNode>(extractNode.Cast<XmlNode>());
var templateFields = nodees.Cast<XmlNode>().Select(x => new
{
field = (String)x.Attributes["userName"].Value,
fieldName = (String)x.Attributes["name"].Value
.Substring(0, x.Attributes["name"].Value.IndexOf(':')),
type = (String)x.Attributes["name"].Value.Substring(x.Attributes["name"].Value
.IndexOf(':') + 1, 4)
}).ToList();
}
return (T)Convert.ChangeType(templateFields, typeof(T));
返回时出现以下错误:
对象必须实现Iconvertible。
我确实了解templateFields
并未实现IConvertible以使用ChangeType。 什么是返回templateFields
的最佳方法
将new()
约束添加到T
并使用以下代码
private static IList<T> GETCG<T>(string test, string type) where T : TestData, new()
{
XmlNodeList extractNode = xdoc.SelectNodes(@".//mediaInstances/mediaInstance/properties/templateFields/templateField", manager);
var nodees = new List<XmlNode>(extractNode.Cast<XmlNode>());
var templateFields = nodees.Cast<XmlNode>().Select(x => new T() //not anonymous type but T object
{
field = x.Attributes["userName"].Value,
fieldName = (string)x.Attributes["name"].Value.Substring(0, x.Attributes["name"].Value.IndexOf(':')),
type = x.Attributes["name"].Value.Substring(x.Attributes["name"].Value.IndexOf(':') + 1, 4)
}).ToList();
return templateFields;
}
我认为这里的问题是,当您select new { ... }
时,您正在选择一个匿名类型,然后Convert.ChangeType
失败,因为匿名类型仅包含public read-only
属性,并且未实现IConvertible
。 相反,我们要选择一个新的T
但是为了做到这一点,我们还必须在T
上包括一个new()约束 ,这意味着T
必须具有默认的构造函数(以便我们可以创建它的实例)。
这样,我们就不需要转换任何东西,因为Select
的结果就是List<T>
。
您还可以通过在一行中选择IEnumerable<XmlNode>
来减少某些代码,而不是创建第二个变量并在第一个变量上进行cast
。
这样的事情应该起作用:
private static IList<T> GETCG<T>(string test, string type) where T : TestData, new()
{
IEnumerable<XmlNode> templateFieldNodes = xdoc
.SelectNodes(".//mediaInstances/mediaInstance/properties/templateFields/templateField",
manager)
.Cast<XmlNode>();
return templateFieldNodes.Select(x => new T
{
field = (String)x.Attributes["userName"].Value,
fieldName = (String)x.Attributes["name"].Value
.Substring(0, x.Attributes["name"].Value.IndexOf(':')),
type = (String)x.Attributes["name"].Value.Substring(x.Attributes["name"].Value
.IndexOf(':') + 1, 4)
}).ToList();
}
您声明了接口TestData
,但未声明实现它的任何类型。 您不能将偶然碰巧具有相同属性的任何类型强制转换为该接口。 您必须创建一个类或实现它的结构。 同样,使用通常的.NET命名约定,接口名称以大写I
开头,属性名称具有PascalCase。
有了这些声明...
public interface ITestData
{
string Field { get; set; }
string FieldName { get; set; }
string Type { get; set; }
}
public class TestData : ITestData
{
public string Field { get; set; }
public string FieldName { get; set; }
public string Type { get; set; }
}
你可以写
private static IList<ITestData> GETCG(string test, string type)
{
XmlNodeList extractNode = xdoc.SelectNodes(
@".//mediaInstances/mediaInstance/properties/templateFields/templateField", manager);
var nodees = new List<XmlNode>(extractNode.Cast<XmlNode>());
var templateFields = nodees.Cast<XmlNode>().Select(x => (ITestData)new TestData {
Field = (String)x.Attributes["userName"].Value,
FieldName = (String)x.Attributes["name"].Value
.Substring(0, x.Attributes["name"].Value.IndexOf(':')),
Type = (String)x.Attributes["name"].Value.Substring(x.Attributes["name"].Value
.IndexOf(':') + 1, 4)
}).ToList();
return templateFields;
}
请注意,该方法不是通用的。 要使.ToList()
创建一个IList<ITestData>
,必须将新数据(ITestData)new TestData { ... }
转换为接口(ITestData)new TestData { ... }
。
问题是您是否仍然需要该接口,或者是否更喜欢直接使用该类。
如果仍然希望该方法是通用的,则必须告诉它T
必须具有带有new()
约束的默认构造函数。 并且必须使用具体类型来调用该方法。 即,您不能使用该接口调用它,因为该接口没有构造函数。
private static IList<T> GETCG<T>(string test, string type)
where T : ITestData, new()
{
...
var templateFields = nodees.Cast<XmlNode>().Select(x => new T {
...
}).ToList();
return templateFields;
}
然后打电话给
IList<TestData> var result = GETCG<TestData>("hello", "world");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.