There's this common pattern in my software where a database query is done and a list of objects is created from that query where the objects are constructed from a SqlDataReader
.
For example:
public List<Authorization> ReadAuthorizations() {
List<Authorization> authorizations = new List<Authorization>();
using (SqlConnection connection = GetConnection(mConnString)) {
using (SqlDataReader authReader = CmdFactory.Instance.ReadAuthorizations(connection)) {
while (authReader.Read()) {
Authorization auth = new Authorization(authReader);
authorizations.Add(auth);
}
}
}
return authorizations;
}
You can replace Authorization
with any kind of object but the pattern is the same every time. The only variables are the object types and the function that is used to query the database.
List<Authorization> ReadAuthorizations()
List<Login> ReadLogins()
List<Batch> ReadBatches()
// etc
Now I was thinking that this just screams for a generic function and I came up with this:
public List<T> Read<T>(Func<SqlConnection, SqlDataReader> func) where T : new()
{
List<T> objects = new List<T>();
using (SqlConnection connection = GetConnection(_ropsString))
{
using (SqlDataReader reader = func(connection))
{
while (reader.Read())
{
T obj = new T(reader);
objects.Add(obj);
}
}
}
return objects;
}
This ALMOST works except that the object to construct is not allowed to take parameters, VS2k10 says:
'T': cannot provide arguments when creating an instance of a variable type
Is there a way to solve this so the variable type can get a constructor argument?