我如何转换此Func <sampleexpression,ienumerator <string>,bool&gt;&gt;到Func <sampleexpression,bool>&gt;

时间:2016-01-11 19:22:32

标签: c# linq lambda expression-trees

这是我的班级

class SampleExpression
{
    public string str;

    public static bool SampleEnum(SampleExpression s, IEnumerator<string> ien = null)
    {
        while (ien.MoveNext())
        {
            if (s.str == ien.Current)
            {
                ien.Reset();
                return true;
            }
        }
        return false;
    }
}

这就是我在运行时生成表达式树的方法:

    static void Main(string[] args)
    {
        ParameterExpression param1 = Expression.Parameter(typeof(SampleExpression), "token");
        ParameterExpression param2 = Expression.Parameter(typeof(IEnumerator<string>), "args");

        var lstConstant = "1,2,3,4,".Split(new string[] { "," },
                           StringSplitOptions.RemoveEmptyEntries).ToList();

        var enummethod = typeof(SampleExpression).GetMethod("SampleEnum");
        MethodCallExpression methodCall = Expression.Call
                                        (
                                            enummethod,
                                            param1
                                            , param2
                                        );

        var e = Expression.Lambda<Func<SampleExpression, IEnumerator<string>, bool>>(methodCall, param1, param2);
        var l = e.Compile();

        List<SampleExpression> lst = new List<SampleExpression>();
        lst.Add(new SampleExpression { str = "1" }); // matches with lstConstant
        lst.Add(new SampleExpression { str = "2" }); // matches with lstConstant
        lst.Add(new SampleExpression { str = "5" });
        var items = lst.Where(x => l(x, lstConstant.GetEnumerator())).ToList();
    }

现在我可能会以一种错综复杂的方式做到这一点(因为我是Expression树的新手) - 我的要求是:

我有一个逗号分隔的字符串,如"1,2,3,4,"。我想将每个SampleExpression拆分并与类str的字符串参数SampleExpression进行匹配。到目前为止,我已经做了。

但我希望表达式为Func<SampleExpression,bool>。正如您可以看到它的Func<SampleExpression, IEnumerator<string>, bool>

我该如何解决这个问题。

2 个答案:

答案 0 :(得分:2)

表达式汇编对我来说似乎很奇怪,但要真正回答你的问题......

您可以像这样包装已编译的Func:

Func<SampleExpression, bool> lBind = (SampleExpression token) => l(token, lstConstant.GetEnumerator());

这会将枚举数绑定为第二个参数,同时将第一个参数保留为输入。

答案 1 :(得分:1)

我不清楚为什么你要进行动态表达式编译,所以我只关注你的问题陈述:

  

我有一个逗号分隔的字符串,如"1,2,3,4,"。我想将每个SampleExpression拆分并与类str的字符串参数SampleExpression进行匹配。

LINQ实际上提供了一种非常简单的方法来处理这个问题:

    var lstConstant = "1,2,3,4,".Split(new string[] { "," },
                       StringSplitOptions.RemoveEmptyEntries).ToList();

    List<SampleExpression> lst = new List<SampleExpression>();
    lst.Add(new SampleExpression { str = "1" }); // matches with lstConstant
    lst.Add(new SampleExpression { str = "2" }); // matches with lstConstant
    lst.Add(new SampleExpression { str = "5" });

    var items = lst.Where(x => lstConstant.Contains(x.str)).ToList();

如果你想让这个逻辑驻留在SampleExpression类中,那很好:

class SampleExpression
{
    public string str;

    public static bool SampleEnum(SampleExpression s, IEnumerable<string> ien)
    {
        return ien.Contains(s.str);
    }
}

// Usage:
var items = lst.Where(x => SampleExpression.SampleEnum(x, lstConstant))
    .ToList();

如果您希望SampleEnum方法本身返回值以传递到Where子句,则可以改为:

class SampleExpression
{
    public string str;

    public static Func<SampleExpression, bool> SampleEnum(IEnumerable<string> ien)
    {
        return s => ien.Contains(s.str);
    }
}

// Usage:
var items = lst.Where(SampleExpression.SampleEnum(lstConstant))
    .ToList();