score:2
i've managed to do it, source code below. it runs somewhat faster than automapper (not sure if my automapper configuration is the fastest for this task), benchmark is not bulletproof, but on my machine to map 5 million rows took 20.16 seconds using my written mapper and 39.90 using automapper, although it seems that automapper uses less memory for this task (haven't measured it, but with 10 million rows automapper gives result and my mapper fails with outofmemory).
public class mappingparameter<tsource>
{
private readonly delegate setter;
private mappingparameter(delegate compiledsetter)
{
setter = compiledsetter;
}
public static mappingparameter<tsource> create<tresult>(expression<func<tsource, tresult>> expression)
{
var newvalue = expression.parameter(expression.body.type);
var body = expression.assign(expression.body, newvalue);
var assign = expression.lambda(body, expression.parameters[0], newvalue);
var compiledsetter = assign.compile();
return new mappingparameter<tsource>(compiledsetter);
}
public void assign(tsource instance, object value)
{
object convertedvalue;
if (!setter.method.returntype.isassignablefrom(typeof(string)))
{
convertedvalue = convert.changetype(value, setter.method.returntype);
}
else
{
convertedvalue = value;
}
setter.dynamicinvoke(instance, convertedvalue);
}
}
public class datarowmappingconfiguration<tsource>
{
private readonly dictionary<string, mappingparameter<tsource>> mappings =
new dictionary<string, mappingparameter<tsource>>();
public datarowmappingconfiguration<tsource> add<tresult>(string columnname,
expression<func<tsource, tresult>> expression)
{
mappings.add(columnname, mappingparameter<tsource>.create(expression));
return this;
}
public dictionary<string, mappingparameter<tsource>> mappings
{
get
{
return mappings;
}
}
}
public class datarowmapper<tsource>
{
private readonly datarowmappingconfiguration<tsource> configuration;
public datarowmapper(datarowmappingconfiguration<tsource> configuration)
{
this.configuration = configuration;
}
public ienumerable<tsource> map(datatable table)
{
var list = new list<tsource>(table.rows.count);
foreach (datarow datarow in table.rows)
{
var obj = (tsource)activator.createinstance(typeof(tsource));
foreach (var mapping in configuration.mappings)
{
mapping.value.assign(obj, datarow[mapping.key]);
}
list.add(obj);
}
return list;
}
}
public class testclass
{
public string name { get; set; }
public int age { get; set; }
}
[testfixture]
public class datarowmappingtests
{
[test]
public void shouldmappropertiesusingownmapper()
{
var mappingconfiguration = new datarowmappingconfiguration<testclass>()
.add("firstname", x => x.name)
.add("age", x => x.age);
var mapper = new datarowmapper<testclass>(mappingconfiguration);
var datatable = new datatable();
datatable.columns.add("firstname");
datatable.columns.add("age");
for (int i = 0; i < 5000000; i++)
{
var row = datatable.newrow();
row["firstname"] = "john";
row["age"] = 15;
datatable.rows.add(row);
}
var start = datetime.now;
var result = mapper.map(datatable).tolist();
console.writeline((datetime.now - start).totalseconds);
assert.areequal("john", result.first().name);
assert.areequal(15, result.first().age);
}
[test]
public void shouldmappropertyusingautomapper()
{
mapper.createmap<datarow, testclass>()
.formember(x => x.name, x => x.mapfrom(y => y["firstname"]))
.formember(x => x.age, x => x.mapfrom(y => y["age"]));
var datatable = new datatable();
datatable.columns.add("firstname");
datatable.columns.add("age");
for (int i = 0; i < 5000000; i++)
{
var row = datatable.newrow();
row["firstname"] = "john";
row["age"] = 15;
datatable.rows.add(row);
}
var start = datetime.now;
var result = datatable.rows.oftype<datarow>().select(mapper.map<datarow, testclass>).tolist();
console.writeline((datetime.now - start).totalseconds);
assert.areequal("john", result.first().name);
assert.areequal(15, result.first().age);
}
}
score:1
something like thid maybe :
public class mapping<tsource>
{
public void assign<tresult>(tsource instance, tresult value)
{
var property = typeof(tsource).getproperties().firstordefault(p => p.propertytype == typeof(tresult)));
if (property != null)
{
property.setvalue(instance, value, new object[0]);
}
}
}
but your object need to have one property of each type for this to be accurate
we could even make it more generic, but more dangerous :
public void assign<tresult>(tsource instance, tresult value)
{
var property = typeof(tsource).getproperties().firstordefault(p => p.propertytype.isassignablefrom(typeof(tresult)));
if (property != null)
{
property.setvalue(instance, value, new object[0]);
}
}
(this won't work if you have 2 properties inheriting from the same base class)...
Source: stackoverflow.com
Related Query
- List of assignment expressions
- List or Array of String Contain specific word in Html Source Code
- c# Linq or code to extract groups from a single list of source data
- Generating the Shortest Regex Dynamically from a source List of Strings
- Enumerating through list of expressions to filter collection
- How to pass LinQ Expressions from F# to C# code
- LINQ Source Code Available
- .NET 4 Code Contracts: "requires unproven: source != null"
- C# - Populate a list using lambda expressions or LINQ
- query list with linq lambda expressions
- Changing a piece of code into expressions
- Query expressions over source type 'dynamic' or with a join sequence of type 'dynamic' are not allowed
- LINQ query returns old results when source list is re-initialized
- Copy a list of objects to another typed list in one line of code
- C# - Linq optimize code with List and Where clause
- creating Linq to sqlite dbml from DbLinq source code
- Stubbing Code for Test With Linq Expressions and Lambdas
- How can i copy data table records of different field name based on mapping list evaluating condition on source data table?
- Having trouble Aggregating over a list of expressions with Expression.AndAlso
- List Categories and it's count of products with LinQ using Lambda or classic expressions
- Method to add Linq expressions to a list of expressions
- Code to apply expression tree directly to List
- Search by zip code and filter list within specific radius?
- I can't get pagination to show up in every page on a GridView with a list as source
- Accessing a List multiple times in same code block - Any better approach?
- Code practice to handle empty result set in Linq to custom list
- Building a list of expressions via Expression Trees
- Find matched directories using a list of regular expressions
- Code First EF: While searching database table is it possible to retrieve list of items it has in DataModel?
- select from list which has same code
More Query from same tag
- Linq to Entities Selecting Data with Max Date?
- Cannot implicitly convert type 'System.DateTime?' to 'System.DateTime'
- How to group flatten list
- The ':' character, hexadecimal value 0x3A, cannot be included in a name
- Long process method with LINQ Query should be in Queue
- Query in C#: how to find data by only 1 number, for example?
- LINQ in typescript or any alternative
- How can I use IEnumerable.Where().Count() in LINQ query?
- How to process IEnumerable in batches?
- Linq :Query Join And Equals( variable) Not Work
- LINQ - Conditional Join
- When is this LINQ query executed?
- How to batch collection by property, recursively
- LINQ to SQL : Unable to use SQL Server UDFs in LINQ query
- Why is Entity Framework returning null?
- Adding an artificial row to an anonymous Linq resultset
- How do I extract a value from a Linq IQueryable object?
- How do I select the item with the highest value using LINQ?
- lock a database or a set of tables from C# Linq 4.0?
- Bug: List remains in memory if file deleted, and saves data twice if file is deleted
- How to re-implement a Where() operator for PLINQ?
- LINQ "equals" operator on nullable foreign key in NHibernate parent/child relationships
- Using a variable for a LINQ property
- LINQ compare two lists and remove
- The member [class] has no supported translation to SQL
- Updating RadGridView after Editing Records in Real Time
- Gettting the primary key which is autoincrement before saving changes in linqtosql
- Need help in Linq
- Cannot convert lambda expression to type 'bool' because it is not a delegate type
- Wrong List.Sort() behaviour