在运行时使用Type变量创建类型列表 [英] create List of Type using Type variable at runtime

查看:187
本文介绍了在运行时使用Type变量创建类型列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试简化我的方法,在为不同类型和不同动作重复的函数中创建多个变量,最终我将迁移到一个可以处理多个类型的单个函数,但是我正在分阶段执行。我想要能够在其类型中列出对象,而不是列表,而不必在任何地方复制/粘贴对象类型。我曾经希望通过一些非常简单的东西来实现这一点,如

 键入t = typeof(LinkAddy); 
var x = List< t>();

但这不编译。



然后,我尝试了以下答案提供的另一种解决方案:存储变量类型并使用它在运行时创建集合

  static IList createGenericList(Type typeInList){ 
var genericListType = typeof(List<))MakeGenericType(new [] {typeInList});
return(IList)Activator.CreateInstance(genericListType);
}

  static List< T> createGenericList< T>(){
列表< T> genericListType = new List< T>();
return genericListType;
}

所以这里有不同的方法和结果:

  Type ThisType = typeof(LinkAddy); 
//正常的列表方法,意味着我必须复制/粘贴LinkAddy到处
var fromQuery = new List< LinkAddy>();
//创建一个列表,但是我仍然需要将LinkAddy
var fromQuery_IsNew = createGenericList< LinkAddy>();
//提供一个列表,我不需要放置LinkAddy
//,而是一个List< object>而不是List< LinkAddy>所以我使用
//对象的任何地方,我都必须像
// string title =(fromQuery_IsDiff [0]作为LinkAddy)。
var fromQuery_IsDiff = createGenericList(ThisType);

编辑:最终,我不知道运行时的类型,该函数将成为通用的,所以我可以将LinkAddy作为类型或其他类型传递,并根据需要生成列表。第一步只是在整个功能中都有泛型,并且是检查需要更具体的任何东西的类型。这是一个大功能的一部分,涵盖了大约200行代码,与数据库同步的列表验证检查有关(它确定哪个缓存和服务器版本是较新的,以较新的方式发布,如果覆盖到另一个则将其覆盖你有权限这样做)。我有类似于LinkAddy的多个类,它们使用WCF RIA服务进行同步,SilverLight与服务器上的SQL数据库进行同步。条目也存储在执行XML序列化的类中,并将XML文件保存到用户的系统(缓存)中。这使我的代理商能够访问我的大部分网站数据而无需互联网连接,就像他们在客户面前通常情况一样。

解决方案

如果您期望这样做可能有效,这并不是很清楚,特别是给定评论:

  //提供一个列表,我不必放置LinkAddy 
//,但它的一个List< object>而不是List< LinkAddy>所以我使用
//对象的任何地方,我都必须像
// string title =(fromQuery_IsDiff [0]作为LinkAddy)。

如果您知道足够投放到 LinkAddy (这将比使用作为,IMO)更好地作为演员完成,那么您在编译时清楚了解类型。如果您在编译时知道类型,只需将其作为参数。



MakeGenericType 当您不要知道编译时所涉及的类型时,这很有用,这意味着您不能投射...并且您不能使用任何其他的东西你知道类型。



你可能会使用动态打字,但如果你知道会有一个标题属性,也许你真正想要的是一个接口,表达共同点。那么你可能会使用通用的方法来对该接口有约束。



无论如何,你应该考虑在编译时你知道哪些事情,哪些只是知道的在执行时。在大多数情况下,泛型是针对编译时已知的类型,而在执行时通过反射来使用泛型是有可能的,它与设计有一定的对抗,所以在令人沮丧的时候不要惊讶。 p>

I'm trying to simplify my methods in creating several variables in a function which is repeated for different types and different actions, eventually I will migrate to a single function that can handle multiple types but I'm doing it in stages. I would like to be able to make a list of objects in their types instead of List without having to copy/paste the object type everywhere. I had hoped to accomplish this by something really simple like

Type t = typeof(LinkAddy);
var x = List<t>();

but this doesn't compile.

Then I tried a different solution provided by the following answer: Storing variable type and using it to create collections at runtime

static IList createGenericList(Type typeInList) {
    var genericListType = typeof(List<>).MakeGenericType(new[] { typeInList });
    return (IList)Activator.CreateInstance(genericListType);
}

and

static List<T> createGenericList<T>() {
    List<T> genericListType = new List<T>();
    return genericListType;
}

So here's the different methods and their results:

Type ThisType = typeof(LinkAddy);
// The normal list method, means I have to copy/paste LinkAddy everywhere
var fromQuery = new List<LinkAddy>();
// Makes a List, but I still have to put LinkAddy
var fromQuery_IsNew = createGenericList<LinkAddy>();
// Provides a List, I don't have to place LinkAddy
// but its a List<object> and not List<LinkAddy> so wherever I use
// the objects, I'll have to cast the object like
// string title = (fromQuery_IsDiff[0] as LinkAddy).Title;
var fromQuery_IsDiff = createGenericList(ThisType);

Edit: Eventually, I won't know the type at runtime, the function would be made generic so I could pass LinkAddy as a type or some other type and it would generate the lists as needed. The first step is just to have generics all throughout the function and do is checks on the type for anything that needs to be more specific. This is part of a large function that covers about 200 lines of code that has to do with list validation checks for a database sync (it determines which of the cached and server versions are newer and whichever is newer, post an overwrite to the other if you have permissions to do so). I have multiple classes similar to LinkAddy that are sync using WCF RIA services and SilverLight to a SQL database on the server. The entries are also stored in a class that does XML serialization and saves the XML file to the user's system (cached). This allows my agents in the field to have access to the majority of my site data without an internet connection, as is often the case for them in front of customers.

解决方案

It's not really clear how you expect this could possibly work, especially given the comment:

// Provides a List, I don't have to place LinkAddy
// but its a List<object> and not List<LinkAddy> so wherever I use
// the objects, I'll have to cast the object like
// string title = (fromQuery_IsDiff[0] as LinkAddy).Title;

If you know enough to cast to LinkAddy (which would be better done as a cast than using as, IMO) then you clearly know the type at compile time. If you know the type at compile-time, just supply it as a type argument.

Things like MakeGenericType are useful when you don't know the type involved at compile-time, which means you can't cast... and you can't use any of the other things you know about the type anyway.

You could potentially use dynamic typing instead... but if you know that there will be a Title property, perhaps what you really want is an interface instead, expressing the commonality. Then you could potentially use generic methods which have a constraint on that interface.

Anyway, you should think about which things you know at compile-time and which things are only known at execution time. For the most part, generics is aimed at types known at compile-time... while using generics at execution time via reflection is possible, it's sort of fighting against the design, so you shouldn't be surprised when it's frustrating.

这篇关于在运行时使用Type变量创建类型列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆