MSDN Magazine - December 2008 - (Page 70) Extending the Extensions Knowing how the extensions are implemented internally, you can easily extend them. Some objects and methods in the Office object model are not covered by the extensions, and in some cases you might even want to provide user-defined extensions. Figure 8 Logging with LINQ-to-DASL // Provide a logging class for our LINQ-to-DASL queries. internal class DebuggerWriter : TextWriter { public override Encoding Encoding { get { throw new NotImplementedException(); } } public override void WriteLine(string value) { Debug.WriteLine(value); } } // Subclass the extensions Mail class so that we can expose a Size // property that maps to the real Outlook size property. internal class MailEx : Mail { [OutlookItemProperty("http://schemas.microsoft.com/mapi/ proptag/0x0E080003")] public int Size { get { return Item.Size; } } } // Create the ItemsSource manually (this is // what Items.AsQueryable() does implicitly). var source = new ItemsSource (folder.Items); // Set the Log property of the ItemsSource to a TextWriter. // It will be given the DASL query string immediately before // the query is executed in Outlook. source.Log = new DebuggerWriter(); //var filteredItems = (from item in folder.Items.AsQueryable () var filteredItems = (from item in source where item.MessageClass.StartsWith("IPM.Note") && item.Subject.StartsWith("RE:") && item.DateReceived >= DateTime.Now.ToUniversalTime() new TimeSpan(30, 0, 0, 0) select item).ToList(); //foreach (Mail item in filteredItems) foreach (MailEx item in filteredItems) { builder.AppendLine(String.Format("{0},{1},{2}", //item.Date, item.DateReceived, item.Body.Length)); item.Date, item.DateReceived, item.Size)); } From our example application, the most obvious cases are the Excel methods Range.get_Offset, Shapes.AddChart, Shape.Select and Chart.SetSourceData. For all of these, it would be trivial to provide extension methods. Recall that these simply need to be static methods that take as their first parameter an object of the type which you want to extend as shown in Figure 7. Note that, taking the Shapes.AddChart method as an example, this extension method works by virtue of having a different number of arguments from the PIA AddChart method (or any of the extensions overloads). If you tried to provide an extension method that had the same arguments, but was simply strongly typed, the compiler would never call it (because it favors native methods, regardless of the strength of the argument types). We can do this with Word because of its use of by-reference arguments; by providing by-value extensions of Word methods, the compiler is always able to differentiate between the two. The extensions library for Excel actually includes a number of methods that are unreachable by the compiler in this way. It might seem strange to provide methods that the compiler will not use, but they will still show up in IntelliSense and will therefore help the user identify the real types of the arguments. Also, the developer could use these methods with normal static method syntax if desired. With these custom extensions, we can simplify the application code: //lastCell = (Excel.Range)firstCell.get_Offset(r, c); lastCell = (Excel.Range)firstCell.Offset(r, c); //chart = sheet.Shapes.AddChart( // Excel.XlChartType.xlLine, missing, missing, missing, missing); chart = sheet.Shapes.AddChart(Excel.XlChartType.xlLine); //chart.Select(missing); chart.Select(); //excel.ActiveChart.SetSourceData(sheet.Range("A1", lastCell), missing); excel.ActiveChart.SetSourceData(sheet.Range("A1", lastCell)); Figure 9 Using Table in Outlook 2007 //Outlook.Items folderItems = folder.Items; //Outlook.Items filteredItems = folderItems.Restrict(filter); //foreach (Outlook.MailItem item in filteredItems) { // builder.AppendLine(String.Format("{0},{1},{2}", // item.SentOn, item.ReceivedTime, item.Size)); //} // Get a table of mail items, remove the default column set, // and add the specific columns we're interested in instead. table = folder.GetTable(filter, Outlook.OlTableContents.olUserItems); table.Columns.RemoveAll(); table.Columns.Add("SentOn"); table.Columns.Add("ReceivedTime"); table.Columns.Add("Size"); // Iterate the table rows. while (!table.EndOfTable) { Outlook.Row nextRow = table.GetNextRow(); builder.AppendLine(String.Format("{0},{1},{2}", nextRow["SentOn"], nextRow["ReceivedTime"], nextRow["Size"])); } Apart from simply allowing the developer to provide additional extension methods, the extensions library itself supports a degree of extensibility. For example, the LINQ-to-DASL features support pluggable logging (see Figure 8). The ItemsSource class provides a Log property that you can set to any object derived from System.IO.TextWriter. In the example, we can write a simple class that outputs to the debug window. This will then be used internally when the extensions code has completed building the DASL query string from the LINQ query—and this string will be output to the debug window. At the same time, we can subclass the extensions Mail class to expose a public property for the underlying Outlook Size property, using the OutlookItemProperty attribute to establish the mapping. Recall that we previously had to use Body.Length as a workaround because Size is not exposed by the extensions by default. With these additional extension enhancements in place, our example application is complete. We use LINQ-to-DASL to fetch filtered Outlook mail item data, feed that data into Excel to produce a chart, and copy that chart into a Word document, which we finally save as an HTML file. Note that Outlook 2007 introduced the Table object, which is a performance-optimized mechanism for enumerating folder items. It allows you to specify properties as table columns, and to filter and VSTO Power Tools 70 msdn magazine
Table of Contents Feed for the Digital Edition of MSDN Magazine - December 2008 MSDN Magazine - December 2008 Contents Toolbox CLR Inside Out Advanced Basics Cutting Edge Patterns In Practice Team System Real-World WF Visual Studio OBA Tools SOA Data Access Geneva Framework Test Run Foundations Windows With C++ Going Places End Bracket MSDN Magazine - December 2008 MSDN Magazine - December 2008 - (Page Intro) MSDN Magazine - December 2008 - Contents (Page Cover1) MSDN Magazine - December 2008 - Contents (Page Cover2) MSDN Magazine - December 2008 - Contents (Page 1) MSDN Magazine - December 2008 - Contents (Page 2) MSDN Magazine - December 2008 - Contents (Page 3) MSDN Magazine - December 2008 - Contents (Page 4) MSDN Magazine - December 2008 - Contents (Page 5) MSDN Magazine - December 2008 - Contents (Page 6) MSDN Magazine - December 2008 - Contents (Page 7) MSDN Magazine - December 2008 - Contents (Page 8) MSDN Magazine - December 2008 - Contents (Page 9) MSDN Magazine - December 2008 - Contents (Page 10) MSDN Magazine - December 2008 - Toolbox (Page 11) MSDN Magazine - December 2008 - Toolbox (Page 12) MSDN Magazine - December 2008 - Toolbox (Page 13) MSDN Magazine - December 2008 - Toolbox (Page 14) MSDN Magazine - December 2008 - CLR Inside Out (Page 15) MSDN Magazine - December 2008 - CLR Inside Out (Page 16) MSDN Magazine - December 2008 - CLR Inside Out (Page 17) MSDN Magazine - December 2008 - CLR Inside Out (Page 18) MSDN Magazine - December 2008 - CLR Inside Out (Page 19) MSDN Magazine - December 2008 - CLR Inside Out (Page 20) MSDN Magazine - December 2008 - CLR Inside Out (Page 21) MSDN Magazine - December 2008 - Advanced Basics (Page 22) MSDN Magazine - December 2008 - Advanced Basics (Page 23) MSDN Magazine - December 2008 - Advanced Basics (Page 24) MSDN Magazine - December 2008 - Advanced Basics (Page 25) MSDN Magazine - December 2008 - Advanced Basics (Page 26) MSDN Magazine - December 2008 - Advanced Basics (Page 27) MSDN Magazine - December 2008 - Advanced Basics (Page 28) MSDN Magazine - December 2008 - Cutting Edge (Page 29) MSDN Magazine - December 2008 - Cutting Edge (Page 30) MSDN Magazine - December 2008 - Cutting Edge (Page 31) MSDN Magazine - December 2008 - Cutting Edge (Page 32) MSDN Magazine - December 2008 - Cutting Edge (Page 33) MSDN Magazine - December 2008 - Cutting Edge (Page 34) MSDN Magazine - December 2008 - Cutting Edge (Page 35) MSDN Magazine - December 2008 - Cutting Edge (Page 36) MSDN Magazine - December 2008 - Patterns In Practice (Page 37) MSDN Magazine - December 2008 - Patterns In Practice (Page 38) MSDN Magazine - December 2008 - Patterns In Practice (Page 39) MSDN Magazine - December 2008 - Patterns In Practice (Page 40) MSDN Magazine - December 2008 - Patterns In Practice (Page 41) MSDN Magazine - December 2008 - Patterns In Practice (Page 42) MSDN Magazine - December 2008 - Patterns In Practice (Page 43) MSDN Magazine - December 2008 - Team System (Page 44) MSDN Magazine - December 2008 - Team System (Page 45) MSDN Magazine - December 2008 - Team System (Page 46) MSDN Magazine - December 2008 - Team System (Page 47) MSDN Magazine - December 2008 - Team System (Page 48) MSDN Magazine - December 2008 - Team System (Page 49) MSDN Magazine - December 2008 - Team System (Page 50) MSDN Magazine - December 2008 - Team System (Page 51) MSDN Magazine - December 2008 - Real-World WF (Page 52) MSDN Magazine - December 2008 - Real-World WF (Page 53) MSDN Magazine - December 2008 - Real-World WF (Page 54) MSDN Magazine - December 2008 - Real-World WF (Page 55) MSDN Magazine - December 2008 - Real-World WF (Page 56) MSDN Magazine - December 2008 - Real-World WF (Page 57) MSDN Magazine - December 2008 - Real-World WF (Page 58) MSDN Magazine - December 2008 - Real-World WF (Page 59) MSDN Magazine - December 2008 - Real-World WF (Page 60) MSDN Magazine - December 2008 - Real-World WF (Page 61) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 62) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 63) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 64) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 65) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 66) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 67) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 68) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 69) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 70) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 71) MSDN Magazine - December 2008 - SOA Data Access (Page 72) MSDN Magazine - December 2008 - SOA Data Access (Page 73) MSDN Magazine - December 2008 - SOA Data Access (Page 74) MSDN Magazine - December 2008 - SOA Data Access (Page 75) MSDN Magazine - December 2008 - SOA Data Access (Page 76) MSDN Magazine - December 2008 - SOA Data Access (Page 77) MSDN Magazine - December 2008 - SOA Data Access (Page 78) MSDN Magazine - December 2008 - SOA Data Access (Page 79) MSDN Magazine - December 2008 - SOA Data Access (Page 80) MSDN Magazine - December 2008 - SOA Data Access (Page 81) MSDN Magazine - December 2008 - Geneva Framework (Page 82) MSDN Magazine - December 2008 - Geneva Framework (Page 83) MSDN Magazine - December 2008 - Geneva Framework (Page 84) MSDN Magazine - December 2008 - Geneva Framework (Page 85) MSDN Magazine - December 2008 - Geneva Framework (Page 86) MSDN Magazine - December 2008 - Geneva Framework (Page 87) MSDN Magazine - December 2008 - Geneva Framework (Page 88) MSDN Magazine - December 2008 - Geneva Framework (Page 89) MSDN Magazine - December 2008 - Geneva Framework (Page 90) MSDN Magazine - December 2008 - Test Run (Page 91) MSDN Magazine - December 2008 - Test Run (Page 92) MSDN Magazine - December 2008 - Test Run (Page 93) MSDN Magazine - December 2008 - Test Run (Page 94) MSDN Magazine - December 2008 - Test Run (Page 95) MSDN Magazine - December 2008 - Test Run (Page 96) MSDN Magazine - December 2008 - Test Run (Page 97) MSDN Magazine - December 2008 - Test Run (Page 98) MSDN Magazine - December 2008 - Test Run (Page 99) MSDN Magazine - December 2008 - Test Run (Page 100) MSDN Magazine - December 2008 - Foundations (Page 101) MSDN Magazine - December 2008 - Foundations (Page 102) MSDN Magazine - December 2008 - Foundations (Page 103) MSDN Magazine - December 2008 - Foundations (Page 104) MSDN Magazine - December 2008 - Foundations (Page 105) MSDN Magazine - December 2008 - Foundations (Page 106) MSDN Magazine - December 2008 - Foundations (Page 107) MSDN Magazine - December 2008 - Foundations (Page 108) MSDN Magazine - December 2008 - Windows With C++ (Page 109) MSDN Magazine - December 2008 - Windows With C++ (Page 110) MSDN Magazine - December 2008 - Windows With C++ (Page 111) MSDN Magazine - December 2008 - Windows With C++ (Page 112) MSDN Magazine - December 2008 - Going Places (Page 113) MSDN Magazine - December 2008 - Going Places (Page 114) MSDN Magazine - December 2008 - Going Places (Page 115) MSDN Magazine - December 2008 - Going Places (Page 116) MSDN Magazine - December 2008 - Going Places (Page 117) MSDN Magazine - December 2008 - Going Places (Page 118) MSDN Magazine - December 2008 - Going Places (Page 119) MSDN Magazine - December 2008 - End Bracket (Page 120) MSDN Magazine - December 2008 - End Bracket (Page Cover3) MSDN Magazine - December 2008 - End Bracket (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.