# Thursday, August 20, 2009

LINQ to Outlook

VSTO offers a number of classes to access Outlook information, but these classes do not implement IEnumerable<T> and are therefore not useable in a LINQ expression.

I wanted to be able to search for appointments using LINQ and write code that looks like this:

var appointments = new Appointments();

var selectedAppointments = from appointment in appointments
                           where appointment.Start <= end    // end is parameter
                           && appointment.End >= start       // start is parameter
                           && appointment.Categories.Contains("Billable")
                           orderby appointment.Start
                           select appointment;

To do this I converted the Items collection in an Outlook Folder to an IEnumerable<Outlook._AppointmentItem>.
The code for the Appointments class looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace Develop_One.OBiOne
{
    /// <summary>
    /// Class to wrap a collection of Outlook.Items as an IEnumerable of Outlook._AppointmentItem.
    /// Doing this allows you to write LINQ queries against the Appointments.
    /// </summary>
    internal class Appointments : IEnumerable<Outlook._AppointmentItem>
    {
        private Outlook.Items _items;

        /// <summary>
        /// Default constructor will use the items in the default Calendar folder to initialize items collection.
        /// </summary>
        internal Appointments()
        {
            var app = new Outlook.ApplicationClass();
            var cal = app.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
            _items = cal.Items;
        }


        #region IEnumerable<_AppointmentItem> Members

        public IEnumerator<Outlook._AppointmentItem> GetEnumerator()
        {
            // use the private AppointmentsEnumerator.
            return new AppointmentsEnumerator(this._items);
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion

        private class AppointmentsEnumerator : IEnumerator<Outlook._AppointmentItem>
        {
            private System.Collections.IEnumerator _items;

            internal AppointmentsEnumerator(Outlook.Items items)
            {
                _items = items.GetEnumerator();
            }


            #region IEnumerator<_AppointmentItem> Members

            public Outlook._AppointmentItem Current
            {
                get
                {
                    return (Outlook._AppointmentItem)_items.Current;
                }
            }

            #endregion

            #region IDisposable Members

            public void Dispose()
            {
                return;
            }

            #endregion

            #region IEnumerator Members

            object System.Collections.IEnumerator.Current
            {
                get
                {
                    return (Outlook._AppointmentItem)_items.Current;
                }
            }

            public bool MoveNext()
            {
                bool result = _items.MoveNext();
                while (_items.Current is Outlook._AppointmentItem == false && result == true)
                {
                    result = _items.MoveNext();
                }
                return result;
            }

            public void Reset()
            {
                _items.Reset();
            }

            #endregion
        }


    }
    

}
#    Comments [1] |