动态LINQ:有没有通过索引来访问对象数据的方法吗? [英] Dynamic linq: Is there a way to access object data by index?

查看:147
本文介绍了动态LINQ:有没有通过索引来访问对象数据的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些内存与动态Linq的过滤。
我的目标只有一个索引:

I need some in-memory filtering with Dynamic Linq. My objects have only a indexer:

public  object this[int index] { }

我的数据的访问是这样的:对象[0]​​,对象[1],...

The access to my data is like: object[0], object[1],...

所以我的查询是这样的:

So my query is like this:

// get FilterText from user at runtime
// eg. filterText can be: [0] > 100 and [1] = "wpf"
collection.AsQueryable().where(filterText);



有没有办法做到这一点?

Is there any way to do this?

推荐答案

我对你有一些新闻​​。

I have some news for you.

这其实是可能的...但是! (是的,there's一但)。

It is actually possible... BUT! (Yes, there´s a but).

我假设你使用的是动态的LINQ库。然后,您必须使用它 - 关键字,以便能够指定您希望您的应用索引操作当前对象。

I assume you are using the dynamic Linq library. You must then use the "it"-keyword to be able to specify the current object to which you wish to apply your indexing operation.

不过...返回的数据类型你的索引是对象,所以你就不能写[0]> 100 [1] =因为数据类型不匹配。

However... The return datatype of your indexer is object, so you will not be able to write [0] > 100 and [1] = "wpf" because of data type mismatch.

另外的WPF即使您从DynamicObject派生,并会增加在运行时的属性,这些属性将不会在运行时通过电流汇入作业状态动态LINQ库解决。你只想得到一个字段或属性不类型XXX存在。

Also, even if you derive from DynamicObject and would add the properties at runtime, those properties would not be resolved at runtime by the dynamic linq library in it´s current state. You would just get a field or property does not exist in type xxx.

有几种解决方案,这一点,其中的一些可能会接受为一个解决方案。

There are several solutions to this, of which some you may accept as being a solution.


  • 一个丑陋的解决方案,如果你有数据类型的数量有限,说N
    (其中n<数在.NET类型),你可以利用N
    索引与参数匹配,并得到你想要的数据类型。对于
    例如,如果您有大多整数和一些字符串:

  • One ugly solution, if you have a limited number of datatypes, say n (where n < the number of types in .NET), you could use n indexers with parameter matching and get the datatype you want. For example if you have mostly ints and some strings:

it[0] > 100 AND it[1, "dummy"] = "wpf" //The dummy parameter allows you to specify return type.


  • 另外一个丑陋的解决方案,动态的LINQ有使用
    的ToString()的支持和转换的方法,因此,你可以比如写
    相同的查询如上:

  • Another ugly solution, Dynamic Linq has support for using the ToString() and Convert-methods, so, you could for instance write the same query as above:

    Convert.ToDouble(it[0]) > 100 AND it[1].ToString() = "wpf".
    


  • 第三个丑陋的解决方案,你可以使用,你包
    语句的约定在告诉你如何将数据转换的方法。对于
    例如,你可以写:

  • A third ugly solution, you could use a convention where you wrap statements in a way which tells you how to convert the data. For example, you could write:

    it[0] > 100 AND it{1} = "wpf"
    

    和替换它[和Convert.ToDouble (它[等等...

    And replace "it[" with "Convert.ToDouble(it[" and so on...

    如果I'm正确的,我认为你不容使用与库通用索引无论是。而Convert.ChangeType对你没有很好的在这种情况下,由于返回类型仍然是反对。

    If I´m correct, I think that you can´t use a generic indexer with the library either. And Convert.ChangeType does you no good in this case since the return type is still object.

    也许我或其他人将改写图书馆借了一些时间来支持这​​些类型的东西,但我没有时间在不久的将来(几周)这样做。

    Maybe I or someone else will rewrite the library some time to support these kinds of things, but I have no time to do so in the near future (some weeks).

    好吧,我很抱歉,但从来就一定是​​在15分钟的地方,所以我们就会有后,我希望!

    Well, I´m sorry, but I´ve got to be somewhere in 15 min, so we´ll have to take the nicer solutions later I hope!

    瞬移自己的会议<采取更好的解决方案/ EM>

    teleporting myself to the meeting

    更新:

    我想我可能已经找到了解决办法你(和我)的问题!

    I think I may have found a solution to your (and my) problem!

    在DLINQ库,你可以在IxxxSignatures接口(S)为你想成为的类型添加成员。能够与工作

    In the DLINQ library, you could add a member in the IxxxSignatures interface(s) for the type for which you would want to be able to work with.

    所以,我在IEqualitySignatures中加入(例如):

    So, I added (for example) in the IEqualitySignatures:

    void F(Object x, Int32 y);
    

    和修改的(在这种情况下)在像这样的其他块ParseComparison-方法

    And modified the (in this case) ParseComparison-method in the else block like this.

    left = Expression.Convert(left, right.Type);
    

    和,不管你信不信,它的工作:)

    And, believe it or not, it worked :)

    我没有测试过各种的操作,因为我还没有加签名的其它类型和操作,但它应该是相当简单的事情!

    I have not tested all kinds of operations, since I have not added the signatures for the other types and operations, but it should be quite straight forward to do!

    更新

    以上更新..

    I'米试验一些更多的关于这一点,虽然它可能不是最漂亮的解决方案,要么,你可以做这样的事情(数据对象仅仅是一个索引器DynamicObject):

    I´m experimenting some more on this and while it might not be the prettiest solution either, you could do something like this (DataObject is just a DynamicObject with an indexer):

        [TestMethod]
        public void DynamicTest()
        {
            List<DataObject> dataObjects = new List<DataObject>();
    
            dynamic firstObject = new DataObject();
            dynamic secondObject = new DataObject();
    
            firstObject.dblProp = 10.0;
            firstObject.intProp = 8;
            firstObject.strProp = "Hello";
    
            secondObject.dblProp = 8.0;
            secondObject.intProp = 8;
            secondObject.strProp = "World";
    
            dataObjects.Add(firstObject);
            dataObjects.Add(secondObject);
    
            /* Notice the different types */
            string newQuery = FormatQuery("dblProp > 9.0 AND intProp = 8 AND strProp = 'Hello'");
    
            var result = dataObjects.Where(newQuery);
    
            Assert.AreEqual(result.Count(), 1);
            Assert.AreEqual(result.First(), firstObject);
        }
    

    和一些类似格式的方法(假装从来就写了一个完整的方法):

    And some kind of format method like (pretend I´ve written a complete method):

        public string FormatQuery(string query)
        {
            query = query.Replace('\'', '\"');
    
            string[] operators = new string[] { "<", ">", "!=", "<=", ">=", "<>", "=" };
    
            string[] parts = query.Split();
    
            for (int i = 0; i < parts.Length; i++)
            {
                if (operators.Contains(parts[i]))
                {
                    parts[i - 1] = "it[\"" + parts[i - 1] + "\"]";
                }
            }
    
            return String.Join(" ", parts);
        }
    

    我们当然可以有一个扩展法来代替。

    We could of course have an extension-method instead.

    或...我们可以把方法在DLINQ lib中使用类似(不是说这是一个好主意,虽然):

    Or... We could put the method in the DLINQ lib using something like (not saying it a good idea though):

    if (typeof(T).GetInterface("IDynamicMetaObjectProvider", true) != null)
        whereClause = whereClause.FormatQuery();
    

    和,检查类型实现了课程的字符串索引器,像(忽略IndexerName这里属性):!

    And, check if the type implements a string-indexer of course, something like (ignoring IndexerName attribute here):

    if (t.GetType().GetProperty("Item") != null)
    

    这将使普通用户写的:

    data.Where("dblProp > 9.0 AND intProp = 8 AND strProp = 'Hello'")
    

    好吧,也许没有汇入作业好有东西在里面,但你明白了吧。你可以有! :)

    Well, maybe it´s not good to have that stuff in there, but you get the point. You could have! :)

    这篇关于动态LINQ:有没有通过索引来访问对象数据的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆