我已經彎腰了一陣子,但我想我錯過了一些東西,所以可能有人會幫助。賦值表達式列表
比方說,我有以下映射類:
public class Mapping<TSource, TResult>
{
private readonly Action<TSource, TResult> setter;
public Mapping(Expression<Func<TSource, TResult>> expression)
{
var newValue = Expression.Parameter(expression.Body.Type);
var body = Expression.Assign(expression.Body, newValue);
var assign = Expression.Lambda<Action<TSource, TResult>>(body, expression.Parameters[0], newValue);
setter = assign.Compile();
}
public void Assign(TSource instance, TResult value)
{
setter(instance, value);
}
}
而且這是工作的罰款:
[Test]
public void ShouldMapProperty()
{
var testClass = new TestClass();
var nameMapping = new Mapping<TestClass, string>(x => x.Name);
var ageMapping = new Mapping<TestClass, int>(x => x.Age);
nameMapping.Assign(testClass, "name");
ageMapping.Assign(testClass, 10);
Assert.AreEqual("name", testClass.Name);
Assert.AreEqual(10, testClass.Age);
}
事情是,我想保持對單個對象類型映射到一些收集和只要不同的屬性具有不同的類型,TResult就會受到阻礙。 如何很好地擺脫TResult?
更新: 貌似我不太清楚,所以這將是樣品我會怎麼使用它:
public class Mapping<TSource, TResult>
{
private readonly Action<TSource, TResult> setter;
private readonly string columnName;
public Mapping(Expression<Func<TSource, TResult>> expression, string columnName)
{
this.columnName = columnName;
var newValue = Expression.Parameter(expression.Body.Type);
var body = Expression.Assign(expression.Body, newValue);
var assign = Expression.Lambda<Action<TSource, TResult>>(body, expression.Parameters[0], newValue);
setter = assign.Compile();
}
public void Assign(TSource instance, DataRow row)
{
setter(instance, row[columnName]);
}
}
然後,我會有些MappingConfiguration類,它可以讓我做這樣的:
MappingConfiguration.For<TestClass>()
.Map(x => x.Name, "FirstName")
.Map(x => x.Age, "Age");
而且finaly一些MappingEngine類,這將需要的DataTable和MappingConfiguration作爲輸入,併產生IEnumerable<TestClass>
作爲輸出。
更新2: 我已經修改了最初的版本到這一點:
public class Mapping2<TSource>
{
private readonly Delegate setter;
public Mapping2(Expression<Func<TSource, object>> expression)
{
var newValue = Expression.Parameter(expression.Body.Type);
var body = Expression.Assign(expression.Body, newValue);
var assign = Expression.Lambda(body, expression.Parameters[0], newValue);
setter = assign.Compile();
}
public void Assign(TSource instance, object value)
{
setter.DynamicInvoke(instance, value);
}
}
它幾乎工作。
通過幾乎我的意思是它的工作原理與引用類型的屬性,並與值類型的屬性,我得到:
System.ArgumentException:表達式必須可寫
參數名:左
如果我理解正確,你想分配爲分配和映射=>映射? –
Kek
2012-07-18 08:37:57
我不明白你在問什麼。 – 2012-07-18 08:40:10
也許[AutoMapper的QueryableExtensions](https://github.com/AutoMapper/AutoMapper/blob/master/src/AutoMapper/QueryableExtensions.cs)的方法會激勵你。他們使用兩階段投影來保持兩個通用參數不同。 – 2012-07-18 08:53:56