我已经做了基本的事情,但我仍然坚持创建实际的LambaExpresion:
任何人都有一些关于我想写的内容的指针? var COPYEXPRESSION = ...
public Expression<Func<TSource, TDestination>> GetOrCreateMapExpression<TSource, TDestination>()
{
return (Expression<Func<TSource, TDestination>>)
_expressionCache.GetOrAdd(new TypePair(typeof(TSource), typeof(TDestination)), tp =>
{
return CreateMapExpression(tp.SourceType, tp.DestinationType);
});
}
private LambdaExpression CreateMapExpression(Type source, Type destination)
{
ParameterExpression instanceParameter = Expression.Parameter(source);
var sourceMembers = source.GetProperties();
var destMembers = destination.GetProperties();
var matchingMembers = sourceMembers.Select(s =>
new
{
Source = s,
Dest = destMembers.FirstOrDefault(d =>
d.Name.Equals(s.Name) && d.PropertyType == s.PropertyType)
}).Where(map => map.Dest != null).ToArray();
var COPYEXPRESSION = ...
return Expression.Lambda(COPYEXPRESSION , instanceParameter);
}
我得到了正确的返回类型,但是在单元测试时,映射的类在属性上为null。
private LambdaExpression CreateMapExpression(Type source, Type destination)
{
ParameterExpression instanceParameter = Expression.Parameter(source);
var instance2Parameter = Expression.New(destination);
LabelTarget returnTarget = Expression.Label(destination);
var sourceMembers = source.GetProperties().Where(p => p.GetMethod.IsPublic);
var destMembers = destination.GetProperties().Where(p => p.SetMethod.IsPublic);
var matchingMembers = sourceMembers.Select(s =>
new
{
Source = s,
Dest = destMembers.FirstOrDefault(d =>
d.Name.Equals(s.Name) && d.PropertyType == s.PropertyType)
}).Where(map => map.Dest != null).ToArray();
var block = Expression.Block(Expression.Block(
matchingMembers.Select(p =>
Expression.Assign(
Expression.Property(instance2Parameter, p.Dest),
Expression.Property(instanceParameter, p.Source)))),
Expression.Label(returnTarget, instance2Parameter));
return Expression.Lambda(block, instanceParameter);
}
这对我有用:
return Expression.Lambda( Expression.MemberInit(Expression.New(destination),
matchingMembers.Select(p =>
Expression.Bind(p.Dest, Expression.Property(instanceParameter, p.Source)))),
instanceParameter);
答案 0 :(得分:1)
鉴于
ParameterExpression instanceParameter = Expression.Parameter(source);
ParameterExpression instance2Parameter = Expression.Parameter(destination);
你需要两个参数,一个用于源,一个用于目的地......
除非您正在构建新目的地,否则您需要Expression.Variable
instance2Parameter
,其中Expression.New
var block = Expression.Block(
matchingMembers.Select(p =>
Expression.Assign(
Expression.Property(instance2Parameter, p.Dest),
Expression.Property(instanceParameter, p.Source)))
这是一个包含所有Expression.Assign
请注意,您应该检查Dest
中是否存在setter,以及Source
中是否存在getter(但最好在sourceMembers.Select
中执行此操作。)