我试图在添加到列表时通过其构造函数创建一个T类型的新对象。
我得到一个编译错误:错误消息是:
'T':创建变量实例时不能提供参数
但是我的类确实有构造函数参数!我该怎么做呢?
public static string GetAllItems<T>(...) where T : new()
{
...
List<T> tabListItems = new List<T>();
foreach (ListItem listItem in listCollection)
{
tabListItems.Add(new T(listItem)); // error here.
}
...
}
补充业绩资料
使用Jeroen van Langen的表达式方法(见上文)对数据库访问和数据模型类填充进行性能测试,并直接实例化数据模型类。
结论:该法表达速度快。
结果:
数据模型类的直接实例:
纪录:3558秒:1.2746019
实例的方法读取列表的类型参数:
记录:3558秒:0.4878858
表达式方法的代码示例:
var list = ReadList<DataModel>(SQLStatement, Connection);
方法ReadList:
注意:所有数据模型类都有一个参数类型为SQLDataReader的构造函数
public static List<pDataModel> ReadList<pDataModel>(string pSQLStatement, SqlConnection pConnection) where pDataModel : new()
{
// constructor of data model
var lType = typeof(pDataModel);
var lParameters = new Type[] { typeof(SqlDataReader) };
var lDataModelConstructor = CreateConstructor(lType, lParameters);
// read data
List<pDataModel> lDataList = new List<pDataModel>();
using (pConnection)
{
SqlCommand lCommand;
lCommand = new SqlCommand(pSQLStatement, pConnection);
pConnection.Open();
SqlDataReader lReader = lCommand.ExecuteReader();
if (lReader.HasRows)
{
while (lReader.Read())
{
pDataModel lDataItem = (pDataModel)lDataModelConstructor(lReader);
lDataList.Add(lDataItem);
}
}
lReader.Close();
pConnection.Close();
}
return lDataList;
}
直接实例化的代码示例:
List<DataModel> list= new List<DataModel>();
using (connection)
{
SqlCommand command;
command = new SqlCommand(SQLStatement, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
list.Add(new DataModel(reader));
}
}
reader.Close();
connection.Close();
}
我有时使用类似于使用属性注入的答案的方法,但使代码更简洁。
它没有一个带有一组属性的基类/接口,只包含一个(虚拟的)Initialize()方法,充当“穷人的构造函数”。
然后,您可以让每个类像构造函数一样处理自己的初始化,这也为处理继承链增加了一种方便的方式。
If经常发现自己处于这样的情况:我希望链中的每个类初始化其唯一属性,然后调用其父类的initialize()方法,该方法反过来初始化父类的唯一属性,以此类推。当具有不同的类,但具有相似的层次结构时,这尤其有用,例如映射到DTO:s的业务对象。
使用普通Dictionary进行初始化的示例:
void Main()
{
var values = new Dictionary<string, int> { { "BaseValue", 1 }, { "DerivedValue", 2 } };
Console.WriteLine(CreateObject<Base>(values).ToString());
Console.WriteLine(CreateObject<Derived>(values).ToString());
}
public T CreateObject<T>(IDictionary<string, int> values)
where T : Base, new()
{
var obj = new T();
obj.Initialize(values);
return obj;
}
public class Base
{
public int BaseValue { get; set; }
public virtual void Initialize(IDictionary<string, int> values)
{
BaseValue = values["BaseValue"];
}
public override string ToString()
{
return "BaseValue = " + BaseValue;
}
}
public class Derived : Base
{
public int DerivedValue { get; set; }
public override void Initialize(IDictionary<string, int> values)
{
base.Initialize(values);
DerivedValue = values["DerivedValue"];
}
public override string ToString()
{
return base.ToString() + ", DerivedValue = " + DerivedValue;
}
}
为了在函数中创建泛型类型的实例,必须使用"new"标志约束它。
public static string GetAllItems<T>(...) where T : new()
但是,只有当你想调用没有参数的构造函数时,这才会起作用。这里不是这样。相反,您必须提供另一个参数,允许基于参数创建对象。最简单的是函数。
public static string GetAllItems<T>(..., Func<ListItem,T> del) {
...
List<T> tabListItems = new List<T>();
foreach (ListItem listItem in listCollection)
{
tabListItems.Add(del(listItem));
}
...
}
然后你可以这样称呼它
GetAllItems<Foo>(..., l => new Foo(l));