MSDN Magazine - December 2007 - (Page 65) decisions. VSTO solutions always require FullTrust because they interop with unmanaged code (the Office host), and this requirement extends to the WPF and WCF pieces that form part of the solution on the client. With Visual Studio 2005 and with projects for Office 2003 in Visual Studio 2008, you need to set up security specifically for the client-side WCF .config file (the app.config for the WordImageSelecter.dll). This is because the .config file is an entry point into the code and must be explicitly trusted in CAS policy. When building projects for Office 2007 in Visual Studio 2008, this is no longer necessary because trust is granted to a solution, including any dependent assemblies and other ancillary files that form part of the solution. At this point, you can test the add-in again now that both the WPF and WCF pieces are in place. ConstantExpression ce = (ConstantExpression)be.Right; this.Application.Selection.InsertAfter( String.Format(“{0} chars, {1} four-letter words [{2} {3} {4}] {5}”, charCount, fourLetterWords.Count, be.NodeType, me.Member.Name, ce.Value, Environment.NewLine)); Using LINQ, XLinq, and Lambda Expressions in VSTO The final piece to explore is the use of LINQ in the context of a VSTO solution. With Visual Studio 2008, most projects automatically include references to System.Core and System.Xml.Linq, where most of the LINQ classes are defined. LINQ is a set of language extensions that allows you to perform SQL-like queries on an open-ended range of data sources in a type-safe manner. In the sample add-in, all the LINQ work is done in the FishEyeClickEvent handler, where I perform some simple analyses on the XML data returned from the WCF service. Although the example is simple, it illustrates how powerful the feature is. To begin with, I can use XLinq to extract the Key and Definition from the XML string, instead of the more cumbersome XPath I used initially: XElement item = XElement.Parse( Globals.ThisAddIn.serviceClient.GetDefinition(e.ButtonName)); String keyText = (string)item.Element(“Key”); String definitionText = (string)item.Element(“Definition”); The last feature to use is extension methods. Many people complain that developing code in C# for Office is painful because many methods in the Office object models take a large number of optional parameters and (especially with Word), in many cases, parameters must be passed explicitly by reference. This is not a problem with Visual Basic because Visual Basic takes care of the translation for you and hides the underlying complexity. For example, the code listed earlier to move the selection to the end of the previous insertion required calling the GoTo method. This method takes four parameters, all explicitly passed by reference, and includes two that are optional. To mitigate this problem, I can write an extension method, which is a static method in a custom class. I can make it look like it extends one of the Office interfaces by specifying that interface as the type of the first parameter, which must also use the this keyword. This extension method can internally use the standard Office GoTo method: public static class RangeExtender { public static void GoTo(this Word.Application wordApplication, Word.WdGoToItem gotoItem, Word.WdGoToDirection gotoDirection) { object what = gotoItem; object which = gotoDirection; object missing = Type.Missing; wordApplication.Selection.GoTo( ref what, ref which, ref missing, ref missing); } } Another feature of LINQ is implicitly typed local variables. Type inference is invoked by using the var keyword to instruct the compiler to infer the type of a variable from the expression in which it is used. Here, we’ll use this technique to get the count of characters in the Definition text: var chars = from c in definitionText select c; int charCount = chars.Count(); I can then use this extension method in place of the one defined by the Office object model: this.Application.GoTo( Word.WdGoToItem.wdGoToLine, Word.WdGoToDirection.wdGoToLast); The Future of Office-Based Apps As more and more developers build Office-based solutions with managed code, it becomes increasingly important that features introduced in the .NET Framework and in new releases of Visual Studio work seamlessly within an Office context. In this article, you’ve seen how you can build a VSTO solution that uses WPF, WCF, and LINQ to utilize services from within an Office application. The example solution uses a simple WCF service to retrieve static data, parses the data with LINQ, and uses WPF to provide an enhanced UI. A more typical real-world solution would likely use a range of WCF services to work with multiple server-side LOB systems, and could use WPF to provide sophisticated data visualization in addition to UI elements. LINQ could be used either on the server, in the middle tier, or on the client to build intuitive, maintainable functionality for data querying and manipulation. It is clear that the designer enhancements for WPF integration with Windows Forms and compiler enhancements for languageintegrated querying make Visual Studio 2008 a compelling addition to your enterprise development toolbox. ■ Office Services december2007 65 Next, we can use a lambda expression to get the number of fourletter words in the Definition text. A lambda expression is similar to an anonymous delegate: List definitionWords = new List (definitionText.Split(new char[] { ‘ ‘ })); var fourLetterWords = definitionWords.FindAll( x => (x.Length == 4)); Besides using lambda expressions in place of anonymous delegates, you can also build an expression tree from lambda expressions. This allows you to treat code (the lambda expression) as if it were data. In the following example, I take the lambda expression y => (y.Length == 4) and map it to an Expression object so that I can output a LISP-style translation of the expression. In this example, this expression will produce the output “Equal Length 4”: Expression<Func > f = y => (y.Length == 4); BinaryExpression be = (BinaryExpression)f.Body; MemberExpression me = (MemberExpression)be.Left;
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.