Wednesday, 10 July 2013

C# Dynamic Types

With C# 4.0 we saw the introduction of dynamic types. Objects declared as dynamic are assumed to support any property and method and are therefore not checked by the compiler when you build your solution. If you declare an object as dynamic and attempt to use a property or method not supported by that object a run-time exception will be generated.

So, how might we use dynamic types? Consider the code below. I have a WebBrowser object and I want to get all anchor tags in the current document, iterate through each of these anchor tags until I find one linking to news.google.co.uk then I want to click this link.

  1. HtmlElementCollection elements = browser.Document.GetElementsByTagName("A");
  2.  
  3. foreach (HtmlElement element in elements)
  4. {
  5.     HTMLAnchorElement anchor = element.DomElement as HTMLAnchorElement;
  6.  
  7.     if (anchor.href != null && anchor.href.IndexOf("news.google.co.uk") > 0)
  8.     {
  9.         anchor.click();
  10.         break;
  11.     }
  12. }

The System.Windows.Forms namespace contains only the generic HtmlElement type and has no element specific properties or methods such as href and click (I am aware there are GetAttribute and InvokeMember methods on HtmlElement but for the purpose of demonstrating dynamic types I shall ignore them!).

If any of you have done much work with HtmlElement then I'm sure you will have come across the DomElement property. HtmlElement is a wrapper for the COM based Document Object Model and the DomElement is the pointer used to query for COM interfaces not exposed by .NET. To use this pointer we add a reference to Microsoft.mshtml library and a "using mshtml" statement. I can then cast the HtmlElement.DomElement pointer to the HTMLAnchorElement interface found in Microsoft.mshtml.

That's enough about the DOM, but what about these dynamic types? Instead of having a reference Microsoft.mshtml, we can declare our anchor object as a dynamic type and set it directly from the HtmlElement.DomElement. We now have access to any properties or methods exposed by HTMLAnchorElement, the only downside is we don't get intellisense for a dynamic type and the compiler doesn't check for typos on those property and method names. Here's the code.

  1. HtmlElementCollection elements = browser.Document.GetElementsByTagName("A");
  2.  
  3. foreach (HtmlElement element in elements)
  4. {
  5.     dynamic anchor = element.DomElement;
  6.  
  7.     if (anchor.href != null && anchor.href.IndexOf("news.google.co.uk") > 0)
  8.     {
  9.         anchor.click();
  10.         break;
  11.     }
  12. }

No comments:

Post a comment