[英]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.