Here s a solution using AutoMapper:
Func<Cat, bool> GetMappedSelector(Func<Dog, bool> selector)
{
Func<Cat, Dog> mapper = Mapper.CreateMapExpression<Cat, Dog>().Compile();
Func<Cat, bool> mappedSelector = cat => selector(mapper(cat));
return mappedSelector;
}
<><>UPDATE: 这是我第一次回答以来的1.5年,我今天在我的回答中看到了扩大,因为人们正在问,在你有代表而不是代表时如何这样做。
原则上,解决办法相同——我们需要能够compose 。 这两项职能(selector
和mapper
)合并为单一职能。 不幸的是,由于在C#中没有任何东西可以“召唤”另一个表达方式(如我们与代表一样),我们可以在法典中直接体现这一点。 例如,以下法典将无法编纂:
Expression<Func<Cat, bool>> GetMappedSelector(Expression<Func<Dog, bool>> selector)
{
Expression<Func<Cat, Dog>> mapper = Mapper.CreateMapExpression<Cat, Dog>();
Expression<Func<Cat, bool>> mappedSelector = cat => selector(mapper(cat));
return mappedSelector;
}
因此,创建我们组成职能的唯一途径是利用<条码>System.Linq.Expressions课程建立http://msdn.microsoft.com/en-us/library/bb3951%7928v=vs.90%29.aspx>expression 树我们自己。
我们确实需要修改<代码> > > > > > <> > > > > > > > > > > > ...... > > ...... > ...... > ...... ...... ...... 这将成为我们的新陈词典,即:<>>>>>>>。
为了替换参数一,创建了一个子级:http://msdn.microsoft.com/en-us/library/bb882521%28v=vs.90%29.aspx>ExpressionVisitor。 能够tra树和用任意表述取代单一参数的类别:
class ParameterReplacer : ExpressionVisitor
{
private ParameterExpression _parameter;
private Expression _replacement;
private ParameterReplacer(ParameterExpression parameter, Expression replacement)
{
_parameter = parameter;
_replacement = replacement;
}
public static Expression Replace(Expression expression, ParameterExpression parameter, Expression replacement)
{
return new ParameterReplacer(parameter, replacement).Visit(expression);
}
protected override Expression VisitParameter(ParameterExpression parameter)
{
if (parameter == _parameter)
{
return _replacement;
}
return base.VisitParameter(parameter);
}
}
然后,我制定了一种延伸方法,即Compose(
),该方法利用访问者来编造两个拉姆布达语,一个外语和一个内语:
public static class FunctionCompositionExtensions
{
public static Expression<Func<X, Y>> Compose<X, Y, Z>(this Expression<Func<Z, Y>> outer, Expression<Func<X, Z>> inner)
{
return Expression.Lambda<Func<X ,Y>>(
ParameterReplacer.Replace(outer.Body, outer.Parameters[0], inner.Body),
inner.Parameters[0]);
}
}
现在,随着所有基础设施的建立,我们可以修改我们的<代码>GetMappedSelector()方法,使用我们的<代码>Compose(的延伸:
Expression<Func<Cat, bool>> GetMappedSelector(Expression<Func<Dog, bool>> selector)
{
Expression<Func<Cat, Dog>> mapper = Mapper.CreateMapExpression<Cat, Dog>();
Expression<Func<Cat, bool>> mappedSelector = selector.Compose(mapper);
return mappedSelector;
}
我创建了一个,用于测试这方面的情况。 我希望,我的解释不会被过分混淆;但不幸的是,几乎没有一种更简单的做法来做你重新努力做的事情。 如果你仍然被完全混淆,至少你可以重新使用我的法典,并赞赏处理 expression树的微妙和复杂性!