Lambda表达式使用参数和属性初始化类

时间:2016-04-04 04:41:46

标签: c# lambda expression-trees

我有一个方法用于生成NewExpression

public NewExpression CreateNewExpression( Expression<Func<T>> expression )
{
    return expression.Body as NewExpression;
}

然后你可以做这样的事情。

CreateNewExpression( () => new MyType() );

稍后用于创建委托,可以执行该委托以创建对象。

var body = Expression.MemberInit( constructorExpression, bindings );
var funcType = typeof( Func<> ).MakeGenericType( objectType );
var lambda = Expression.Lambda( funcType, body ).Compile();

这很好用,但现在我想将一些数据传递给方法,以便它可以用于构造对象。

public NewExpression CreateNewExpression( Expression<Func<T, Data>> expression )

然后就可以这样使用。

CreateNewExpression( data => new MyType( data.Id ) );

我不能为我的生活弄清楚如何创建正确的表达式来传递数据以供构造函数使用。

如果我没有从CreateNewExpression中的表达式中提取正文并执行Expression.Invoke,我不知道如何在之后设置属性。

如果我提取正文,我可以使用Expression.MemberInit设置属性,但后来我无法弄清楚如何将数据传递给它。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

如果要使用包含ParameterExpression的表达式,则需要在最终表达式中重用相同的ParameterExpression

为此,您可以访问原始表达式的Parameters,然后将参数传递给Expression.Lambda()。结果可能如下所示:

public Delegate M<T>(Expression<Func<Data, T>> expression)
{
    var objectType = typeof(T);

    var constructorExpression = (NewExpression)expression.Body;
    var constructorParameterExpression = expression.Parameters.Single();

    var bindings = …;

    var body = Expression.MemberInit( constructorExpression, bindings );
    var funcType = typeof( Func<,> ).MakeGenericType( typeof(Data), objectType );
    var lambda = Expression.Lambda( funcType, body, constructorParameterExpression )
        .Compile();

    return lambda;
}

答案 1 :(得分:0)

我认为问题的答案可能是Expression.Parameter

我在geeks with blogs找到了一个利用此内容的博客条目。此解决方案的唯一缺点是,当您需要三个以上的参数时,您必须创建新的重载。但我想这可以通过params object[]轻松解决。