Как использовать Dynamic linq с индексом вместо имени свойства - PullRequest
3 голосов
/ 27 января 2012

У меня есть ICollection с объектами:

private ObservableCollection<ViewItem> items;

ViewItems не имеет свойств.Доступ к данным будет осуществляться через индекс с

public  object this[int index] {
   get{ .... }
   set {....}
}

. У меня есть общий класс для фильтрации.Линк с свойствами будет работать нормально.Я использую (только важный код):

Queryable = CreateQueryable((IEnumerable<object>)mItemsSource.SourceCollection, ItemType);
mQuery = Queryable.Where(filterString).Cast<object>();
ilteredCollection = mQuery.ToList();

с:

private static IQueryable CreateQueryable(IEnumerable<object> collection, Type itemType)
{
        if (itemType == null) return null;

        var queryableList = collection.AsQueryable();
        return queryableList.Provider.CreateQuery(
            Expression.Call(
                typeof(Queryable), "Cast",
                new Type[] { itemType },
                queryableList.Expression));
}

Так что я могу использовать строку фильтра, например: Id>10 или Name="abc", где Id иName - это имена свойств.

Но у меня есть объект в другой коллекции, доступ к которому возможен только через индекс.поэтому у меня есть строка где, например:

[0]>10 or [1]="abc"

Я не нашел никакого решения.Единственный совет, который я могу найти, это использовать:

new(it([idx] as Type)

, где idx - индекс элемента, а Type - тип этого элемента

например,

[0]>10 --> new(it[0] as object)>10

Но затем я получаю сообщение об ошибке:

{"Operator" = 'несовместим с типами операндов' DynamicClass1 'и' Int32 '"}

Использование строки вмой фильтр вроде:

new(it[0] as object)>"10" 

, чем ошибка:

{"Operator" = 'несовместим с типами операндов' DynamicClass1 'и' string '"}

Итак - как мне решить эту проблему.Поскольку это общий класс фильтров, я также не знаю тип .Поэтому в выражении как я могу использовать только объект или что-то подобное.

Я надеюсь, что кто-нибудь может мне помочь.Возможно, ключевое слово dynamic в C # 4.0 поможет ??Кстати, обходной путь будет заключаться в том, чтобы создать в каждом классе оболочку с индексатором, но это будет много глупой работы.И это то, что настоящий программист не любит;).Я уверен, что есть решение!

Ответы [ 2 ]

1 голос
/ 28 июня 2013

взбодрись !!

Прежде всего - Как получить доступ к текущему экземпляру?

При синтаксическом анализе лямбда-выражения с одним безымянным параметром члены безымянного параметра автоматически попадают в область видимости в строке выражения, ина текущий экземпляр, заданный безымянным параметром, можно ссылаться целиком, используя ключевое слово it.Например,

Customers.Where ("Страна = @ 0", страна);

эквивалентно

Customers.Where ("it.Country = @ 0", страна);

Вышеприведенная концепция была объяснена здесь .

Из приведенного выше объяснения мы теперь можем получить доступ к свойству индексатора, так как оно [@ 0], где @ 0 - этоЗначение индекса для передачи, как описано ниже.

// Рассмотрим ниже класса

public class Product
{
    private NameValueCollection collection = new NameValueCollection();
    public string Company { get; set; }
    public string Distributor { get; set; }
    public int ID { get; set; }
    ...

    public string this[string index]
    {
        get { return collection[index]; }
        set { if(!string.IsNullOrEmpty(value)) collection[index]=value; }
    }
}

// Основной код

        List<Product> list = new List<Product>();
        Product product = new Product() { Company = "Nestle", Distributor = "xyz", ID = 1 };
        product["Name"] = "Maggi";
        list.Add(product);
        var filteredList = list.AsQueryable().Where("it[@0]=@1", "Name", "Maggi"); //Accessing the current item by indexer property

        foreach (Product productItem in filteredList)
        {
            Console.WriteLine(productItem.Company);
        }

Надеюсь, это поможет вам !!:)

0 голосов
/ 29 января 2012

Вы используете ключевое слово new неправильно.Он не вызывает объект (и не as).

Ключевое слово new используется для создания нового объекта анонимного класса с указанными свойствами.Таким образом, new(it[idx] as Type) создаст новый объект со свойством Type, имеющим значение it[idx].Это эквивалентно C #: new { Type = this[idx] }.

Как я уже указывал в Динамический linq: есть ли способ получить доступ к данным объекта по индексу? , вам нужно привести его вследующим образом: Int32(it[0]) > 10 для вашего псевдопроса [0] > 10.

...