有如下方法:
public T GetList<T>(....)现在我在外面需要调用此方法 ,但在调用的时候,我需要动态指定T,我也知道T所在的程序集和类名。请问,如何调用?
List<??> a = GetList<??>(...);如上,问号处要动态指定,不允许写死,请问怎么写?谢谢!

解决方案 »

  1.   

    泛型不是这么用的,不知道有没有什么好的做法,我们一般的做法是给函数传一个Type变量
      

  2.   

    借助Object(所有类型的祖先)List <Object> a = GetList <Object>(...); 
    不过,如果的是值类型,要装箱和拆箱,效率会差点.
      

  3.   

    什么意思?没看明白,本来就不用指定
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;namespace WindowsApplication2
    {
        public partial class Form1 : Form
        {
            public T GetList<T>(T t)
            {
                if (t is int)
                    MessageBox.Show("int " + t.ToString());
                else if (t is float)
                    MessageBox.Show("float " + t.ToString());
                else
                    MessageBox.Show("String " + t.ToString());
                return t;
            }        public Form1()
            {
                InitializeComponent();            int i = 100;
                float f = 123.4f;
                String s = "a";            i = GetList(i);
                f = GetList(f);
                s = GetList(s);
            }
        }
    }
      

  4.   

    真有才啊~~给你的T们写个公用的接口吧.
    list<接口> 吧.
      

  5.   

    不考虑使用object,因为现在在开发一个插件框架的CMS,而数据持久层我们自己已经写好。扔回来的结果是List<T>,我主框架需要根据不同的插件来指定不同的T,T的程序集和类名,都可以通过插件接口获取的到。但如何创建?现在不可能再去动数据持久层,将它改成List<object>,这样装箱拆箱效率肯定有影响。
      

  6.   

    真有才啊~~给你的T们写个公用的接口吧.
    list <接口> 吧.
    -------------------------------
    各T的属性完全不一样,所以不可能用接口实现 。
      

  7.   


    返回来的是object ,如果要返回的是Int和String ....你除非方法有个参数告诉object是什么...没有还真不知道有什么好办法.
      

  8.   

    你看看这个将DataSet转为IList,这就是动态传的,方法里面都是对T进行反射处理  public static IList<T> DataSetToIList<T>(DataSet DataSet, int TableIndex)
            {
                if (DataSet == null || DataSet.Tables.Count < 0)
                    return null;
                if (TableIndex > DataSet.Tables.Count - 1)
                    return null;
                if (TableIndex < 0)
                    TableIndex = 0;            System.Data.DataTable dt = DataSet.Tables[TableIndex];
                IList<T> result = new List<T>();
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    T t = (T)Activator.CreateInstance(typeof(T));
                    PropertyInfo[] propertys = t.GetType().GetProperties();
                    foreach (PropertyInfo pi in propertys)
                    {
                        for (int i = 0; i < dt.Columns.Count; i++)
                        {                        if (pi.Name.Equals(dt.Columns[i].ColumnName))
                            {
                                if (dt.Rows[j][i] != DBNull.Value)
                                    pi.SetValue(t, dt.Rows[j][i], null);
                                else
                                    pi.SetValue(t, null, null);
                                break;
                            }
                        }
                    }
                    result.Add(t);
                }
                return result;
            }
      

  9.   

    public T GetList<T>(T t)
            {
                if (t is int)
                    MessageBox.Show("int " + t.ToString());
                else if (t is float)
                    MessageBox.Show("float " + t.ToString());
                else
                    MessageBox.Show("String " + t.ToString());
                return t;
            }-------------------------------
    我是动态加载插件的,插件是由其他人开发,需要用的时候装载进来,如果按你这样写就好办了,关键是现在根本不知道外面有多少种插件,各插件的数据是什么类型。
      

  10.   

    不使用Object,那么就如7楼所说,所有对象,统一使用你们定下来的接口,这样的思路才是正途.
    不客气得说,是你原来的思路有问题!
      

  11.   

    public static IList<T> DataSetToIList<T>(DataSet DataSet, int TableIndex)
            {
                if (DataSet == null || DataSet.Tables.Count < 0)
                    return null;
                if (TableIndex > DataSet.Tables.Count - 1)
                    return null;
                if (TableIndex < 0)
                    TableIndex = 0;            System.Data.DataTable dt = DataSet.Tables[TableIndex];
                IList<T> result = new List<T>();
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    T t = (T)Activator.CreateInstance(typeof(T));
                    PropertyInfo[] propertys = t.GetType().GetProperties();
                    foreach (PropertyInfo pi in propertys)
                    {
                        for (int i = 0; i < dt.Columns.Count; i++)
                        {                        if (pi.Name.Equals(dt.Columns[i].ColumnName))
                            {
                                if (dt.Rows[j][i] != DBNull.Value)
                                    pi.SetValue(t, dt.Rows[j][i], null);
                                else
                                    pi.SetValue(t, null, null);
                                break;
                            }
                        }
                    }
                    result.Add(t);
                }
                return result;
            }
    -----------------------------------------
    此方法跟我们的数据持久层里用的方法一样,这种方法在外面调用的时候会指定类型的,所以跟我问的问题完全是两码事,谢谢!
      

  12.   

    不使用Object,那么就如7楼所说,所有对象,统一使用你们定下来的接口,这样的思路才是正途.
    不客气得说,是你原来的思路有问题!
    -------------------------------------------
    我们的接口已经定义过了。就是GetLIst<T>,具体,它只要扔LIST出来就行了,主程序里会去遍历,会根据插件字典去读需要用到的属性的。而各插件的数据,也就是T,是完全不一样,不做限定的。

    插件->飞机,可能有两个属性,翅展长度,发动机数
    插件->大葱,有属性,长度,产地
      

  13.   

    这种需求往往是设计有误的提示 - 
    使用泛型符号T,是为了充分利用强类型检查带来的好处,包括编译期类型检查和代码提示。
    而运行期才能知道T则失去了这些好处,这种情况还不如直接用非泛型的ArrayList,或使用接口。下面代码中的GetList(Type)体现了这种尴尬的实现。
    public partial class Form1 : Form
    {
        public object GetList(Type type)                        //<--- object
        {
            MethodInfo mi = typeof(Form1).GetMethod("GetList"); 
            MethodInfo gi = mi.MakeGenericMethod(type);         //<---
            return gi.Invoke(null, null);
        }    public static List<T> GetList<T>()
        {
            return new List<T>();
        }}
      

  14.   

    正如1楼所说,如果你无法确定数据类型,无论怎么封装你将来如何调用呢?如果要那么写还不如 object a=... 来的实在
      

  15.   

    问题主要在于你要对这个T进行些什么操作,传进来的话都是动态的,你GetList<T>这里指定的是T,传来是什么就认什么
    如果要动态创建对象实例、获取属性之类的可以
     T t = (T)Activator.CreateInstance(typeof(T));
    PropertyInfo[] propertys = t.GetType().GetProperties();
    所以重点应该是想好你这个方法要进行些什么操作,反射处理应该是必须的
      

  16.   

    List <"+ a +"> a = GetList <"+ b +">(...); 乱写的,呵呵
      

  17.   

    这种需求往往是设计有误的提示 -
    使用泛型符号T,是为了充分利用强类型检查带来的好处,包括编译期类型检查和代码提示。
    而运行期才能知道T则失去了这些好处,这种情况还不如直接用非泛型的ArrayList,或使用接口。下面代码中的GetList(Type)体现了这种尴尬的实现。C# code    public partial class Form1 : Form { public object GetList(Type type) //<--- object { MethodInfo mi = typeof(Form1).GetMethod("GetList"); MethodInfo gi = mi.MakeGenericMethod(type); //<--- return gi.Invoke(null, null); } public static List<T> GetList<T>() { return new List<T>(); } }-----------------------------------------
    这种办法是可以返回出来,但你这个跟我直接返回object又有什么不同呢?因为如果你返回object,那我在外面就要拆箱,如何将object又拆成List<??>呢?
      

  18.   

    问题主要在于你要对这个T进行些什么操作,传进来的话都是动态的,你GetList <T>这里指定的是T,传来是什么就认什么
    如果要动态创建对象实例、获取属性之类的可以
    T t = (T)Activator.CreateInstance(typeof(T));
    PropertyInfo[] propertys = t.GetType().GetProperties();
    所以重点应该是想好你这个方法要进行些什么操作,反射处理应该是必须的 
    --------------------------------------------
    反射创建,获取属性,设置属性值这些我都知道,
    关键是:List<??> a = GetList<??>,这个问号这里,我只知道程序集名和类名,如何实现这句话?只要实现了这句话,其他的问题都不是问题了。
      

  19.   

    List <??> a = GetList <??>(...); ??处放一类型,但是这个类型却是未知的,只知道它存于在字典?
    现在需要把字典中:"UnknowClass"字符串“转”成一个 UnknowClass 类型,List <UnknowClass> a = GetList <UnknowClass >(...); 这样???
      

  20.   


    这个和接口实现理论一至!并且可以实现.
    比如:
    Class UnknowClass 
    {
       public string DataName;//类型名称
       public object DataObj;//数据
    }
    想用的时候,通过DataName来决定你想转成哪个数据.....
      

  21.   


    不可以转的,你如何根据DataName生成并执行以下语句?
    List<"Dataname"> t = new List<"DataName">();
      

  22.   

    我想26楼的意思是把UnknowClass当“容器”。整个程序集都不存在这种类型,现在仅仅有类型的名字,就要凭空创建出这个类型,我觉得不大可能。
    而且没了类型,反射也无力了。
      

  23.   

    为什么每次来CSDN都得不到答案?????虽然大家很热情,回复速度也很快,谢谢大家的捧场!以下是MSDN上提问后被选中的答案:周雪峰 2009年3月30日 16:30:320 投票
    你好!
         如果你想通过反射来获取类型,然后指定泛型方法的话,似乎不可行。
         因为通过反射只能获得Type实例,这个不能用来指定泛型方法啊!
    --------------------------------------------------------------------------------
    周雪峰
    Sheng Jiang 蒋晟MVP2009年3月31日 2:19:340 投票
    泛型是编译时的语法,运行时要使用泛型的话,需要用自动化代码编译器。 
    微软不建议使用泛型来做公开接口。--------------------------------------------------------------------------------
    MSMVP VC++