3

I have an ICollection with objects:

private ObservableCollection<ViewItem> items;

The viewItems have no properties. The data will be accessed via an index with

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

I have a geneal class for filtering. The linq with properies will work fine. I use (the important code only):

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

with:

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));
}

So I can use a filter string like: Id>10 or Name="abc" where Id and Name are property names.

But I have also Object in another collection which only have access via index. so I have an where string like:

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

I didn't find any solution. The only hint I could find is to use:

new(it([idx] as Type)

where idx is element index and Type is a type of this element

e.g.

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

But than I get the error:

{"Operator '=' incompatible with operand types 'DynamicClass1' and 'Int32'"}

Useing a string in my filter like:

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

than the error is:

{"Operator '=' incompatible with operand types 'DynamicClass1' and 'string'"}

So - how can I solve this problem. Because this is a general Filterclass I also don't know the type. So in the as statement I can only use object or something like this.

I hope anyone can help me. Perhaps the dynamic keyword of C# 4.0 will help?? BTW a workaround will be to impement a wrapper in each class with indexer, but this will be a lot of stupid work. And that is something a real programmer don't like ;). I am sure there is a solution!

Krizz
  • 11,362
  • 1
  • 30
  • 43
Schorsch
  • 137
  • 1
  • 12

2 Answers2

1

Cheer up !!

First of all -- How to access Current Instance ?

When parsing a lambda expression with a single unnamed parameter, the members of the unnamed parameter are automatically in scope in the expression string, and the current instance given by the unnamed parameter can be referenced in whole using the keyword it. For example,

customers.Where("Country = @0", country);

is equivalent to

customers.Where("it.Country = @0", country);

Above concept has been explained here.

From above explanation, we can now access the indexer property as it[@0] where @0 is value of index to be passed, as explained below.

//Consider below class

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; }
    }
}

//Main Code

        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);
        }

Hope this helps you !! :)

0

Your usage of new keyword is wrong. It does not cast object (nor does as).

Keyword new is used to create new object of anonymous class with the specified properties. Thus new(it[idx] as Type) will create new object with property Type having the value it[idx]. It is equivalent to C#'s: new { Type = this[idx] }.

As I have already pointed out in Dynamic linq: Is there a way to access object data by index?, you need to cast it in the following manner: Int32(it[0]) > 10 for your pseudo-query [0] > 10.

Community
  • 1
  • 1
Krizz
  • 11,362
  • 1
  • 30
  • 43