We knew there are at least 3 implementation in .Net 3.5, they are LINQ to Objects, LINQ to XML and LINQ to SQL. I don't believe Microsoft will create different pattern for those.
In my current open source project NFlickr, because I have thousands of the fotos at flickr.com , so I don't want to get everything and then filter it using the LINQ to Objects. I want to filter it on the server side and still use the same syntax.
It's not easy, so I figured out that we need to start from something simple.In the previous post LINQ Tips #3--Why you can not use LINQ? , I already had a Student class and a Classroom class.
What I need to do is to change the class Classroom inherited from IQueryable<Student>, not IEnumerable<Student> (We could make it generic, but we will do it later), The new Classroom class will be :
1: public class ClassRoom2 : IQueryable<Student>, IEnumerator<Student>
2: {
3: private List<Student> students = new List<Student>();
4: private int _index = 0;
5: public void Add(Student student)
6: {
7: students.Add(student);
8: }
9: #region IEnumerable<Student> Members
10: public IEnumerator<Student> GetEnumerator()
11: {
12: return (IEnumerator<Student>)this;
13: }
14: #endregion
15: #region IEnumerable Members
16: IEnumerator IEnumerable.GetEnumerator()
17: {
18: return GetEnumerator();
19: }
20: #endregion
21: #region IEnumerator<Student> Members
22: public Student Current
23: {
24: get { return students.ElementAt(_index-1); }
25: }
26: #endregion
27: #region IDisposable Members
28: public void Dispose()
29: {
30:
31: }
32: #endregion
33: #region IEnumerator Members
34: object IEnumerator.Current
35: {
36: get { return Current; }
37: }
38: public bool MoveNext()
39: {
40: _index++;
41: if (_index > students.Count)
42: {
43: return false;
44: }
45: return true;
46: }
47: public void Reset()
48: {
49: _index = 0;
50: }
51: #endregion
52: #region IQueryable Members
53: public Type ElementType
54: {
55: get { throw new NotImplementedException(); }
56: }
57: public System.Linq.Expressions.Expression Expression
58: {
59: get {
60: throw new NotImplementedException();
61: }
62: }
63: public IQueryProvider Provider
64: {
65: get {
66: throw new NotImplementedException();
67: }
68: }
69: #endregion
70: }
We will notice that there are three new properties which are ElementType,Expression,Provider.What's those three property means, and how can we get the right implementation? The answer is that we need to have the Classroom inherited from another interface--IQueryProvider.
And we will have the three property implementation as :
1: public class ClassRoom2 : IQueryable<Student>, IEnumerator<Student>, IQueryProvider
2: {
3: #region IQueryable Members
4:
5: public Type ElementType
6: {
7: get { return typeof(Student); }
8: }
9:
10: public System.Linq.Expressions.Expression Expression
11: {
12: get {
13: return System.Linq.Expressions.Expression.Constant(this);
14: }
15: }
16:
17: public IQueryProvider Provider
18: {
19: get {
20: return this;
21: }
22: }
23:
24: #endregion
25: }
Then we need to implement the new four methods for the interface IQueryProvider:
The key method for us is the Method IQueryable<TElement> CreateQuery<TElement>(System.Linq.Expressions.Expression expression).To understand this method, I will suggest you to watch the video at Channel 9.
Tomorrow, I will continue on this topic and finish the full implementation and you will know how powerful the LINQ can be!