我的朋友正在尝试创建一个给定Type
的实用程序函数,并在该函数中创建该类型的通用List。我们在创建该列表时遇到了麻烦:
public static List<T> GetQueryResult(string xpathQuery, Type itemType) {
// this line does not work:
List<itemType> lst = new List<itemType>();
return lst;
}
这有什么简单的解决方案吗?
更新
有没有办法基本上这样做?
List<T> lst = new List<T>();
foreach (Sitecore.Data.Items.Item i in items) {
lst.Add(new T(i));
}
答案 0 :(得分:22)
public static List<T> GetQueryResult<T>(string xpathQuery/*, Type itemType you don't need this because you specified the Type with T*/) {
// this line works now:
List<T> lst = new List<T>();
return lst;
}
然后你会这样调用这个方法:
List<int> results = GetQueryResult<int>("xpathQuery");
修改强>
你想做这样的事吗?
List<YourType> lst = items.Select<Sitecore.Data.Items.Item, YourType>(
siteCoreItem => new YourType()
{
PropertyA = siteCoreItem.PropertyA,
}
);
如果YourType继承自Sitecore.Data.Items.Item,则可以使用Cast:
List<YourType> list = items.Cast<YourType>();
答案 1 :(得分:3)
定义这样的方法:
public static List<T> GetQueryResult<T>(string xpathQuery)
{
List<T> lst = new List<T>();
// do stuff
return lst;
}
并将其称为:
List<SomeType> items = SomeClass.GetQueryResult<SomeType>("query");
答案 2 :(得分:1)
虽然Elisha的回答向您展示了如何从Type实例创建构造的泛型类型,但它不会对您有所帮助,因为我认为您想要做的事情是不可能的:GetQueryResult方法的签名是非法的,因为T是未指定(除非该方法本身是泛型类型的成员)。
该方法不会按照给定的方式进行编译。
如果您已经知道类型,可以将其更改为
public static List<T> GetQueryResult<T>(string xpathQuery)
{
var lst = new List<T>();
return lst;
}
但这可能不是你想要的......
答案 3 :(得分:0)
可以使用反射,例如:
var type = typeof(int); // var type = itemType : put this line to fit the method
var genericListType = typeof(List<>).MakeGenericType(type);
var genericList = Activator.CreateInstance(genericListType);
Assert.IsTrue(genericList is List<int>);
在您的示例中,您是否从返回类型中使用了T?也许没有必要在这里使用反思。
如果你没有将T作为泛型参数,那么你不能将List作为泛型List返回,并且该方法必须返回非泛型类型(如IList而不是List)。
答案 4 :(得分:0)
通用类型参数在编译时被解析,因此要使代码正常工作,您需要将itemType作为类型参数传递或将返回类型更改为IList并使用ELisha给出的解决方案但这意味着丢失类型信息在呼叫网站上
答案 5 :(得分:0)
public static List<T> GetQueryResult<T>(string xpathQuery) {
List<T> lst = new List<T>();
return lst;
}
如果你想要静态输入,是唯一的方法。否则你可以做
public static IList GetQueryResults(string xpathQuery, Type itemType) {
Type tp = typeof(List<>).MakeGenericType(itemType);
IList lst = (IList)Activator.CreateInstance(tp);
return lst;
}
但在这种情况下使用非通用列表可能会更好。
编辑:您在同一篇文章中提到了另一个问题:
创建泛型类型实例的3种方法是
public static List<T> GetQueryResults<T>(string xpathQuery, Func<int, T> creator) {
var result = new List<T>();
foreach (i in something)
result.add(creator(i));
return result;
}
然后调用它:
List<int> l = GetQueryResults("something", i => new MyObject(i));
答案 6 :(得分:0)
回答更新的问题:
public List<T> GetQueryResult<T>(string xPathQuery)
{
var items = ;// logic to get items
var list = new List<T>();
foreach (Sitecore.Data.Items.Item item in items)
{
list.Add((T) Activator.CreateInstance(typeof(T), item));
}
return list;
}
我假设T有一个获取Sitecore.Data.Items.Item的构造函数,如果它没有代码将在运行时失败。
必须有一种更安全的方法,如果能够为问题提供更广泛的背景,那就更好了。
答案 7 :(得分:0)
正如其他人所证明的那样,解决任何T
更新问题的唯一方法就是反思。但是,如果T
仅限于您可以修改的众所周知的类型集,则可以执行此操作:
public interface IItemContainer
{
void SetItem(Sitecore.Data.Items.Item item);
}
public static List<T> GetQueryResult<T>(string xpathQuery)
where T : IItemContainer, new() {
IList<Sitecore.Data.Items.Item> items = GetAListOfItemsSomehow(xpathQuery);
List<T> result = new List<T>();
foreach (Sitecore.Data.Items.Item item in items) {
T obj = new T();
obj.SetItem(item);
result.add(obj);
}
return result;
}
您要用于T
的任何类型都必须实施IItemContainer
。