C#泛型实例化

时间:2012-06-21 17:44:59

标签: c# generics

全部,我有一个返回List的方法。此方法用于根据名称返回SQL StoredProcedures,Views和Functions的参数。我想要做的是创建一个对象列表并将此列表返回给调用者。方法如下

private List<T> GetInputParameters<T>(string spFunViewName)
{
    string strSql = String.Format(
        "SELECT PARAMETER_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.PARAMETERS " +
        "WHERE SPECIFIC_NAME = '{0}' AND PARAMETER_MODE = 'IN';",
        spFunViewName);
    List<string[]> paramInfoList = new List<string[]>();
    DataTable paramDt = Utilities.DTFromDB(conn, "InputParmaters", strSql);
    if (paramDt != null)
    {
        Converter<DataRow, string[]> rowConverter =
            new Converter<DataRow, string[]>(Utilities.RowColConvert);
        paramInfoList = Utilities.ConvertRowsToList<string[]>(paramDt, rowConverter);
    }
    else
        return null;

    // Build the input parameter list.
    List<T> paramList = new List<T>();
    foreach (string[] paramInfo in paramInfoList)
    {
        T t = new T(paramInfo[NAME], paramInfo[TYPE], Convert.ToInt32(paramInfo[CHARMAXLEN]));
        columnList.Add(column);
    }
    return columnList;   
}

显然无法通过T实例化new并传递给构造函数,但应该清楚我正在尝试做什么。有没有办法用另外三种方法做我想做的事情?

请注意。主要问题是我传递给T的参数数量可以是两个 OR 三个。

感谢您的时间。

编辑:我使用的struct如下

public struct Database
{
    public string name { get; set; }
    public string filename { get; set; }
    public List<Table> tables { get; set; }
    public List<StoredProcedure> sps { get; set; }
    public List<Function> funcs { get; set; }
    public List<View> views { get; set; }
    public Database(string name, string filename)
    {
        this.name = name;
        this.filename = filename;
    }
}

protected internal struct StoredProcedure
{
    public string name { get; set; }
    public List<string[]> parameters { get; set; }
    public StoredProcedure(string name, List<string[]> parameters)
    {
        this.name = name;
        this.parameters = parameters;
    }
}

protected internal struct Function
{
    public string name { get; set; }
    public string output { get; set; }
    public List<string[]> parameters { get; set; }
    public Function(string name, string output, List<string[]> parameters)
    {
        this.name = name;
        this.output = output;
        this.parameters = parameters;
    }
}

protected internal struct View
{
    public string name {get; set;} 
    public List<string[]> parameters { get; set; }
    public View(string name, List<string[]> parameters)
    {
        this.name = name;
        this.parameters = parameters;
    }
}

7 个答案:

答案 0 :(得分:6)

使用Activator类创建T并传递参数。

Type type = typeof(T);
var result = (T)Activator.CreateInstance(type, new object[] { yourParameters });

在您的代码段中使用:

T t = Activator.CreateInstance(type, colInfo[NAME], colInfo[TYPE], Convert.ToInt32(colInfo[CHARMAXLEN]));

答案 1 :(得分:3)

我既不赞同也不贬低这种技巧,但你可以使用:

(T) Activator.CreateInstance( typeof(T), colInfo[TYPE], Convert.ToInt32(colInfo[CHARMAXLEN]) );

我想我宁愿拥有单独的工厂方法。

答案 2 :(得分:3)

您可以像其他提到的那样使用Activator.CreateInstance()或传递委托Func<string, string, int, T>,避免反射开销。

 List<T> GetInputParameters<T>(string spFunViewName, Func<string, string, int, T> itemCreator)
 {

    ....
    List<T> paramList = new List<T>();     
    foreach (string[] paramInfo in paramInfoList)     
    {         
       T t = itemCreator(paramInfo[NAME], paramInfo[TYPE], 
            Convert.ToInt32(paramInfo[CHARMAXLEN]));         
      paramList.Add(t);     
    }     

    return columnList;    
 }

答案 3 :(得分:2)

  

我显然无法通过new实现T并传递给构造函数

如上所述,不;但是,如果您将类型参数限制为仅接受带有构造函数的类型,则可以

private List<T> GetInputParameters<T>(string spFunViewName) where T : new()
{
    // your code here
}

在上面的示例中,您可以说:

T myItem = new T();

在您的特定情况下,您似乎期望每种泛型类型共享一些共同点。考虑使用接口约束类型:

private List<T> GetInputParameters<T>(string spFunViewName) where T : new(), ISomeInterface
{
    // your code here
}

这将允许您在实例化对象后,将值应用于接口上的任何属性:

T myItem = new T();

myItem.SomeProperty = somevalue;
myItem.AnotherProperty = anothervalue;

有关详细信息,请查看MSDN上的Constraints on Type Parameters (C# Programming Guide)以获取有关泛型类型约束的更多信息。

答案 4 :(得分:1)

您可以使用列表&lt; DbParameter&gt;

这有点明显。

答案 5 :(得分:1)

你可以试试这个:

var constructor = typeof(T).GetConstructor(typeof(string), typeof(string), typeof(int));
constructor.Invoke(colInfo[NAME], colInfo[TYPE], Convert.ToInt32(colInfo[CHARMAXLEN]));

答案 6 :(得分:1)

您可以使用ADO.NET DbProviderFactories创建通用数据库参数(以及连接和命令等)。

  

System.Data.Common命名空间提供用于创建的类   DbProviderFactory实例用于处理特定数据源。什么时候   您创建一个DbProviderFactory实例并传递它的信息   数据提供者,DbProviderFactory可以确定正确的,   强类型连接对象,根据信息返回   已经提供。

在您的代码中,您可以创建DbProviderFactory,然后拨打CreateParameter()

string providerName = ConfigurationManager.ConnectionStrings["YourConnectionString"].ProviderName;
DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);
DbParameter parameter = factory.CreateParameter();