动态LINQ:有没有通过索引来访问对象数据的方法吗? [英] Dynamic linq: Is there a way to access object data by index?
问题描述
我需要一些内存与动态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屋!