c # лямбда-выражение, построенное с помощью LinqKit, не компилируется - PullRequest
0 голосов
/ 22 апреля 2010

Эта лямбда не компилируется, но я не понимаю почему.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using LinqKit;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
    {
        var barModel = new BarModel();
        string id = "some";

        Console.WriteLine(barModel.subFor(id).ToString());
            // output: m => (True AndAlso (m.key == value(ConsoleApplication2.Bar`1+<>c__DisplayClass0[ConsoleApplication2.Model]).id))
        Console.ReadKey();


        var subworkitems = barModel.list.Where(barModel.subFor(id).Compile());
                // Exception {"variable 'm' of type 'ConsoleApplication2.Model' referenced from scope '', but it is not defined"}

        Console.WriteLine(subworkitems.ToString());
        Console.ReadKey();
    }
}

class Bar<TModel>
{

    public Bar(Expression<Func<TModel, string>> foreignKeyExpression)
    {
        _foreignKeyExpression = foreignKeyExpression;
    }

    private Expression<Func<TModel, string>> _foreignKeyExpression { get; set; }

    public Expression<Func<TModel, bool>> subFor(string id)
    {

        var ex = forTargetId(id);

        return ex;
    }

    public Expression<Func<TModel, bool>> forTargetId(String id)
    {

        var fc = _foreignKeyExpression;

        Expression<Func<TModel, bool>> predicate = m => true;

        var result = predicate.And(m => fc.Invoke(m) == id).Expand();

        return result;

    }

}

class Model
{
    public string key;
    public string value;
}

class BarModel : Bar<Model>
{
    public List<Model> list;

    public BarModel() : base(m => m.key) 
    {
        list = new List<Model>();
    }
}


}

1 Ответ

2 голосов
/ 12 декабря 2010

Решение 1

Это решение не удаляет операторы invoke, которые, как я полагаю, вы пытаетесь сделать, вызывая "Expand".

измените результат "forTargetId (String id)) "to

predicate.And(m => fc.Invoke(m) == id);

Когда выражение скомпилировано в предложении where, оно будет знать, что ему нужно передать" m "в выражение fc выше.

Мой первый совет пришел, когда я изменил

predicate.And(m => fc.Invoke(m) == id).Expand();

на

predicate.And(n => fc.Invoke(n) == id).Expand();

, и я увидел, что n вообще не передается.

Я протестировал это изменение, манипулируя методом Main следующим образом

static void Main(string[] args)
{
    var barModel = new BarModel();
    barModel.list.Add(new Model() { key = "1", value = "One" });
    barModel.list.Add(new Model() { key = "2", value = "Two" });
    barModel.list.Add(new Model() { key = "some", value = "Three" });

    string id = "some";

    Console.WriteLine(barModel.subFor(id).ToString());
    // output: m => (True AndAlso (m.key == value(ConsoleApplication2.Bar`1+<>c__DisplayClass0[ConsoleApplication2.Model]).id))
    Console.ReadKey();


    var subworkitems = barModel.list.Where(barModel.subFor(id).Compile());
    // Exception {"variable 'm' of type 'ConsoleApplication2.Model' referenced from scope '', but it is not defined"}

    foreach (var si in subworkitems)
    {
        Console.WriteLine(si.key);
        Console.WriteLine(si.value);
    }

    Console.WriteLine(subworkitems.ToString());
    Console.ReadKey();
}

Решение 2

Это решение удаляет операторы Invoke с использованием метода Expand, но изменяет способ, которымвы объединяете операторы вместе.

Функция «Развернуть» объявляется на веб-сайте LinqKit следующим образом.

Expression<Func<Purchase, bool>> criteria1 = p => p.Price > 1000;
Expression<Func<Purchase, bool>> criteria2 = p => criteria1.Invoke(p) || p.Description.Contains("a");
Console.WriteLine(criteria2.Expand().ToString());
// p => ((p.Price > 1000) || p.Description.Contains("a"))

Обратите внимание, что они не используют метод «И» дляэти вещи вместе, но вместо этого они «объединяют в цепочку» вызовы вместе.

Вместо

Expression<Func<TModel, bool>> predicate = m => true;
var result = predicate.And(m => fc.Invoke(m) == id).Expand();

Сделайте это

Expression<Func<TModel, bool>> predicate = m => fc.Invoke(m) == id && true;
return predicate.Expand();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...