Simplifying enumeration of Office object model collections with Linq and Extension methods
I found an interesting post on Deborah's Developer MindScape (via Greg’s blog )and wanted to share a modification of the technique that can simplify the use of Office object models in C# and VB. I use this heavily in my VisioAutomation library.
First, let’s look at the the Deborah’s original solution :
var query = from d in Wd.Documents.Cast<Word.Document>()
select d.Name;
SIMPLIFYING WITH EXTENSION METHODS
This works fine. Through the use of extension methods we can make this even more succinct. The core pain to address is the need to re-enter the type (“Word.Document”) when it is already clear that is the only possible kind of object in the collection
A simple extension method makes this even easier:
var query = from d in Wd.Documents.AsEnumerable()
select d.Name;
The extension method that achieved this is trivial
public static class WordExtensions
{
public static IEnumerable<Word.Document> AsEnumerable(this Word.Documents docs)
{
return docs.Cast<Word.Document>();
}
}
SOURCE CODE
The full source code is below ( you can get the entire project from my SkyDrive)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Word = Mi2crosoft.Office.Interop.Word;
namespace DemoOfficeCollectionsIEnumerable
{
class Program
{
static void Main(string[] args)
{
before();
after_with_an_extension_method();
}
public static void before()
{
// Start Word and get Application object
var Wd = new Word.Application();
// Define documents
var doc1 = Wd.Documents.AddEmptyDoc();
var doc2 = Wd.Documents.AddEmptyDoc();
// Use Linq to access the document names.
var query = from d in Wd.Documents.Cast<Word.Document>()
select d.Name;
var docsnames1 = query.ToList();
// Or use Lambda expressions
var query2 = Wd.Documents.Cast<Word.Document>().Select(d=> d.Name);
var docnames2 = query2.ToList();
}
public static void after_with_an_extension_method()
{
// Add to the top of the code file
object missingValue = System.Reflection.Missing.Value;
// Start Word and get Application object
var Wd = new Word.Application();
// Define documents
var doc1 = Wd.Documents.AddEmptyDoc();
var doc2 = Wd.Documents.AddEmptyDoc();
// Use Linq to access the document names.
var query = from d in Wd.Documents.AsEnumerable()
select d.Name;
var docsnames1 = query.ToList();
// Or use Lambda expressions
var query2 = Wd.Documents.AsEnumerable().Select(d => d.Name);
var docnames2 = query2.ToList();
}
}
public static class WordExtensions
{
public static IEnumerable<Word.Document> AsEnumerable(this Word.Documents docs)
{
return docs.Cast<Word.Document>();
}
public static Word.Document AddEmptyDoc(this Word.Documents docs)
{
object missingValue = System.Reflection.Missing.Value;
return docs.Add(ref missingValue, ref missingValue,
ref missingValue, ref missingValue);
}
}
}
PARTING THOUGHTS
- I through in an extra extension method (AddEmptyDoc) and liberal use of ‘var’ to make the sample source code smaller