Click here to Skip to main content
15,893,663 members
Articles / Programming Languages / Visual Basic

LINQ To Flickr, Another IQueryable Implementation

Rate me:
Please Sign up or sign in to vote.
4.80/5 (29 votes)
23 Oct 2007CPOL2 min read 57K   295   38  
This article focuses on how you can extend the great LINQ technology to other domains using the idea of implementation of IQueryable.
using System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.Xml.XLinq;
using System.Data.DLinq;
using System.Expressions;
using FlickrNet;
using System.Collections;

namespace LinqToFlickr
{
    public class PhotoQuery : IQueryable<FlickrPhoto>
    {
        string AppKey;
        Expression _expression;
        string _tags;
        string _title;
        string _photoId;
        DateTime? _dateAdded;
        string _userId;

        public PhotoQuery(string AppKey)
        {
            this.AppKey = AppKey;
        }
        #region IQueryable<FlickrPhoto> Members

        public IQueryable<S> CreateQuery<S>(Expression expression)
        {
            this._expression = expression;
            return (IQueryable<S>)this;
        }

        public S Execute<S>(Expression expression)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IEnumerable<FlickrPhoto> Members

        IEnumerator<FlickrPhoto> IEnumerable<FlickrPhoto>.GetEnumerator()
        {
            return (IEnumerator<FlickrPhoto>)((IEnumerable)this).GetEnumerator();
        }

        #endregion

        #region IQueryable Members

        public IQueryable CreateQuery(Expression expression)
        {
            return CreateQuery<FlickrPhoto>(expression);
        }

        public Type ElementType
        {
            get { return typeof(FlickrPhoto); }
        }

        public object Execute(Expression expression)
        {
            throw new NotImplementedException();
        }

        public Expression Expression
        {
            get { return System.Expressions.Expression.Constant(this); }
        }

        #endregion

        #region IEnumerable
        IEnumerator IEnumerable.GetEnumerator()
        {
            MethodCallExpression methodCall = _expression as MethodCallExpression;
            if ((methodCall == null) || (methodCall.Method.Name != "Where"))
                throw new NotImplementedException();
            foreach (var param in methodCall.Parameters)
            {
                ParseExpression(param);
            }
            return QueryPhotoExpression();
        }
        #endregion

        #region Parsing Logic
        private IEnumerator<FlickrPhoto> QueryPhotoExpression()
        {
            Flickr flickr = new Flickr(AppKey);
            PhotoSearchOptions options = new PhotoSearchOptions();
            options.Tags = _tags;
            options.Text = _title;
            options.UserId = _userId;
            if (_dateAdded.HasValue)
                options.MinUploadDate = _dateAdded.Value;
            Photos photos = flickr.PhotosSearch(options);
            var photoList = new List<FlickrPhoto>(photos.PhotoCollection.Count);
            foreach (Photo p in photos.PhotoCollection)
            {
                photoList.Add(new FlickrPhoto(p));
            }
            return photoList.GetEnumerator();
        }

        private void ParseExpression(Expression param)
        {
            switch (param.NodeType)
            {
                case ExpressionType.AndAlso:
                    AndAlso(param as BinaryExpression);
                    break;
                case ExpressionType.Lambda:
                    ParseExpression(((LambdaExpression)param).Body);
                    break;
                case ExpressionType.MethodCall:
                    MethodCall(param as MethodCallExpression);
                    break;
                default:
                    break;
            }
        }

        private void MethodCall(MethodCallExpression methodCallExpression)
        {
            switch (methodCallExpression.Method.Name)
            {
                case "op_Equality":
                    //Photo.PhotoId == ???
                    //Photo.Title == ???
                    if (methodCallExpression.Parameters[0].NodeType == ExpressionType.MemberAccess)
                    {
                        MemberExpression memberExpr = methodCallExpression.Parameters[0] as MemberExpression;
                        if (memberExpr.Expression.Type == typeof(FlickrPhoto))
                        {
                            if (methodCallExpression.Parameters[1].NodeType == ExpressionType.Constant)
                            {
                                ConstantExpression constant = methodCallExpression.Parameters[1] as ConstantExpression;
                                switch (memberExpr.Member.Name)
                                {
                                    case "Title":
                                        _title = constant.Value.ToString();
                                        break;
                                    case "Tags":
                                        _tags = constant.Value.ToString();
                                        break;
                                    case "PhotId":
                                        _photoId = constant.Value.ToString();
                                        break;
                                    case "DateAdded":
                                        _dateAdded = (DateTime?)constant.Value;
                                        break;
                                    case "UserId":
                                        _userId = constant.Value.ToString();
                                        break;
                                    default:
                                        break;
                                }
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
        }

        private void AndAlso(BinaryExpression binaryExpression)
        {
            ParseExpression(binaryExpression.Left);
            ParseExpression(binaryExpression.Right);
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Microsoft
United States United States
Mohamed Elsherif
Sr. SDE,
Microsoft
Blogs: www.Bashmohandes.com

Comments and Discussions