全部,我有一个返回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;
}
}
答案 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();