7

所有,我有一个返回列表的方法。该方法用于根据名称返回 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 的参数数量可以是两个三个。

谢谢你的时间。

编辑:struct我使用的 s 如下

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;
    }
}
4

7 回答 7

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]));
于 2012-06-21T17:47:39.503 回答
3

我既不认可也不贬低这种技术,但你可以使用:

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

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

于 2012-06-21T17:48:34.777 回答
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;    
 }
于 2012-06-21T17:53:58.870 回答
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上的类型参数约束(C# 编程指南)以获取有关泛型类型约束的更多信息。

于 2012-06-21T17:58:35.967 回答
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();
于 2012-06-21T17:56:58.600 回答
1

你可以只使用 List< DbParameter >

这更明显一点。

于 2012-06-21T17:49:24.000 回答
1

你可以试试这个:

var constructor = typeof(T).GetConstructor(typeof(string), typeof(string), typeof(int));
constructor.Invoke(colInfo[NAME], colInfo[TYPE], Convert.ToInt32(colInfo[CHARMAXLEN]));
于 2012-06-21T17:50:09.673 回答