Reputation: 375
What alternatives are there to property.setvalue()? I've read that it is very slow. I'm using it to map IDataReader to POCO objects.
This is a truncated version of the code. Everything here is very new to me. I know there a lot of frameworks that accomplish this task. However, we can't use them.
public class DbAutoMapper<T>
{
public IEnumerable<T> MapToList(IDataReader reader)
{
var list = new List<T>();
while (reader.Read())
{
var obj = Activator.CreateInstance<T>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
foreach (var attribute in prop.GetCustomAttributes(true))
{
prop.SetValue(obj, value, null);
}
}
list.Add(obj);
}
return list;
}
}
Upvotes: 4
Views: 2375
Reputation: 1063964
Firstly: why are you repeating the reflection for every attribute, when you don't use the attribute?
Second: assuming you intended to map this by name, column-to-property (which isn't what the code currently does), consider a tool like dapper, which does all this for you, including cached high-performance reflection-emit. It'll also handle the command itself for you. For example:
string region = "North";
var customers = conn.Query<Customer>(
@"select * from Customers where Region = @region",
new { region } // full parameterization, the easy way
).ToList();
If you need more control, consider FastMember, which provides fast member-access (again, reflection-emit), but without being specific to data access:
var accessor = TypeAccessor.Create(typeof(T));
string propName = // something known only at runtime
while( /* some loop of data */ ) {
var obj = new T();
foreach(var col in cols) {
string propName = // ...
object cellValue = // ...
accessor[obj, propName] = cellValue;
}
yield return obj;
}
Upvotes: 5
Reputation: 15579
A few approaches come to mind...
Skip Reflection
public class DbAutoMapper<T> where T : IInitFromReader, new()
{
public IEnumerable<T> MapToList(IDataReader reader)
{
var list = new List<T>();
while (reader.Read())
{
IInitFromReader obj = new T;
obj.InitFromReader(reader);
list.Add(obj);
}
return list;
}
}
Then you'll have to implement the InitFromReader in each of your entitiy objects. Obviously, this skips the benefits of reflection (less code).
Code Generation
Maintaining this code for (InitFromReader) is painful, so you could opt to generate it. This in many ways gives you the best of both worlds:
Upvotes: 1