Content by Category
.NET 1.x
.NET 2.0
.NET 3.0
.NET 3.5
.NET 4.0
.NET 4.5
.NET Assemblies
.NET Framework
.NET Getting Started
Accessibility
ADO.NET
Advertorials
Agile Development
AJAX
Amazon Web Services
Analysis Services
Android
Architecture
Arduino
ASP .NET Web API
ASP.NET
ASP.NET MVC
ASP.NET WebForms
Azure
B2B (Business Integration)
BDD
Big Data
Bing
BizTalk
Book Excerpts
Build and Deploy
Business Intelligence
C#
C++
ClickOnce
Cloud Computing
Code Contracts
CODE Framework Info - non Technical
CODE on the Road!
COM+
Community
Conferences
Continuous Integration
Crystal Reports
CSLA.NET
CSS
Data
Debugger
Design Patterns
Development Process
Display Technologies
Distributed Computing
Document Database
DotNetNuke
DSL
Dynamic Languages
Dynamic Programming
Editorials
Enterprise Services ("COM+")
Entity Framework
Events
Expression Blend
F#
Fox to Fox
Frameworks
Functional Programming
Git
Graphics
HTML 5
Internet Explorer 8.0
Interviews
IOS
iPhone
Iron Ruby
Java
Java Script
JavaScript
jQuery
JSON
Lightswitch
LINQ
Linux
LUA
Mac OS X
MDX
Messaging
Metro
Microsoft Application Blocks
Microsoft Business Rules Framework
Microsoft Dynamics
Microsoft Expression
Microsoft Office
Mobile Development
Mobile PC
Mono
MsBuild
MVVM
MySQL
Network
NHibernate
node.js
NOSQL
Nuget
Object Oriented Development
Objective C
Odata
OLAP
Open Source
Opinion
Opinions
Oracle
ORM
Other Languages
Parallel Programming
Patterns
PHP
Podcasts
Post Mortem
PowerPoint
Print/Output
Prism
Product News
Product Reviews
Project Management
Prolog
Python
Q&A
Rails
Rake
Razor
Reporting Services
REST
RIA Services
Ruby
Ruby on Rails
Scheme
Search
Security
Services
SharePoint
SignalR
Silverlight
SOA
Social Networks
Software & Law
Software Business
Source Control
Speech-Enabled Applications
SQL Server
SQL Server 2000
SQL Server 2005
SQL Server 2008
SQL Server 2012
SQL Server CE/AnyWhere/Mobile/Compact
SSIS
Subversion
Sync Framework
Tablet PC
TDD
Team System
Techniques
Testing and Quality Control
TFS
Tips
TypeScript
UI Design
UML
User Groups
VB Script
VB.NET
Version Control
VFP and .NET
VFP and SQL Server
Virtual Earth
Vista
Visual Basic
Visual Basic 6 (and older)
Visual FoxPro
Visual Studio .NET
Visual Studio 11
Visual Studio 2005
Visual Studio 2008
Visual Studio 2010
Visual Studio 2011
Visual Studio 2012
Visual Studio Tools for Office
VSX
WCF
Web Development (general)
Web Services
WebMatrix
WF
Whitepapers
Windows 7
Windows 8
Windows Azure
Windows Live
Windows Phone 7
Windows Phone SDK
Windows Server
Windows Vista
WinForms
WinRT
Workflow
WPF
XAML
Xiine Documentation
XML
XNA
XSLT



Component One


LearnNow
 


Component One

Reader rating:
Article source: CoDe (2012 May/Jun)


Article Pages: < Previous - 1 2 3  4 


Grokking the DLR: Why it’s Not Just for Dynamic Languages (Cont.)

Accessing the Dynamic Object as an Array

When working with OData, lists of data are very common. To handle them well, you’ll want to add some functionality to your dynamic data classes. You may have noticed in Listing 3 that the DynamicOData class implemented the IEnumerable contract. This isn’t anything special required to enable dynamic typing. The code to do it is easy enough:

public IEnumerator GetEnumerator()
{
  foreach (var element in _current)
    yield return new DynamicOData(element);
}

Just as I returned each named node in TryGetMember as a new DynamicOData object to make chaining possible, the iterator shown here wraps each XElement in the _current collection as a new DynamicOData object so that all of the nice dynamic language semantics we want to apply to the XML document extend to each node. Here’s a bit of test code that uses eBay’s OData feed to find the top ten items on their site pertaining to the same movie that we queried Netflix about.

string ebayQueryFormat =
  "http://ebayodata.cloudapp.net/" +
      "Items?search={0}&$top=10";
string ebayUrl = String.Format(
  ebayQueryFormat, movieTitle);
DynamicOData ebayItems =
  new DynamicOData();
ebayItems.OnDataReady +=
  OnEbayItemsReady;
ebayItems.FetchAsync(ebayUrl);

It’s the same pattern I used for fetching data from Netflix. I’m using the same DynamicOData type that I used to query Netflix. However, the query is a bit different since eBay provides a search verb to which the search term can be assigned. Listing 7 shows the OnEbayItemsReady method that is called when the data is loaded.

The foreach loop shown in Listing 7 takes advantage of the IEnumerable implementation in my DynamicOData class. Inside that loop, since each returned item has been wrapped as a new DynamicOData instance, properties specific to the eBay OData feed like Id, Title and CurrentPrice become resolvable. Of course, if I wanted to ascribe array-like semantics directly to the DynamicOData class, I could do so by overriding TryGetIndex as follows:

public override bool TryGetIndex(
  GetIndexBinder binder, object[] indexes,
  out object result)
{
  int ndx = (int)indexes[0];
  result = new DynamicOData(
    _current.ElementAt(ndx));
  return true;
}

This is a very simplistic implementation that assumes that my indexing strategy is purely numerical. Do you see the cast operation to coerce a single integer from the array? However, any sort of indexing I need is possible. The indexes parameter of the TryGetIndex method is an object array, meaning that C# compiler will pass exactly what’s provided by the caller. There may be one index value or a dozen of them. They could be strings or integers or even complex data types. The sky’s the limit as they say, so I’m free to get as creative as I like with the way in which the index parameters are implemented.

Hopefully, the DynamicOData class I’ve shown here opens your eyes to the possibilities available to you when using the DLR. What I’ve created isn’t about dynamic languages per se. It’s true that C# and Visual Basic feels more dynamic when using a class that’s powered by the IDynamicMetaObjectProvider contract. But C# and Visual Basic are still statically-typed languages under the hood. Deferral of some binding operations until runtime gives them a feeling of being just dynamic enough to make our code more expressive than it’s ever been before. To finish up, let’s spend a bit of time discussing the performance concerns that arise from the code you’ve seen here.

Rule and Call Site Caching

The biggest concern that many developers have with dynamic programming languages is performance. The DLR goes to extraordinary measures to address that concern. I’ve touched briefly on the fact that the CallSite<T> class exists within the namespace called System.Runtime.CompilerServices. Also in that namespace are a number of other classes that perform caching at a variety of levels. Using these types, the DLR implements three major levels of caching to speed up dynamically dispatched operations:

  1. A global rule cache
  2. A local rule cache
  3. A polymorphic delegate cache

The rule caches are used to avoid spending computing resources when binding objects by type for specific call sites. If two objects of type string are passed to a dynamic method and an integer is returned, global and/or local rule caches may be updated to record that pathway to the dynamic code. This can speed up binding in future calls.

The delegate cache, which is managed within the call site object itself, is called polymorphic because the delegates stored there can take many shapes depending on code that’s encountered at runtime and the rules in the other caches used to generate them. As a runtime compiler service, the delegate cache is also sometimes referred to as inline. The reason for that term is that the expressions generated by the DLR and its binders are assembled into MSIL and Just-In-Time (JIT) compiled, just like any other .NET code. This runtime compilation happens in line with the normal flow and execution of your program. As you can imagine, turning dynamic code into compiled .NET code on the fly can make a massive, positive impact on the performance of the application.

With the downloadable source code for this article, I’ve included a second project called PythonIntegration that interfaces some C# code to IronPython. I won’t cover the application here because it’s lengthy and would require a lot more space to describe. You’ll need to download and install IronPython if you want to experiment with the PythonIntegration application, of course. What you’ll discover is the vast difference between the static-to-dynamic language interoperability of the past compared to the high performance options offered by Microsoft’s DLR. Some over-the-border operations from C# to Python, measured in tight repetition, are literally 100,000 times faster using the caching mechanisms that you get for free when using the DLR. These same caching tactics are applied when calling from C# to any other CLR-compliant language, too.

Conclusion

The DLR isn’t just about dynamic languages. It opens up a whole world of possibilities for communicating between disparate systems. As .NET’s language of languages, the DLR enables the movement of code and data with a kind of fluidity and natural expressiveness that weren’t possible beforehand. As you've seen, the language of a data model like OData can be mapped rather generically into the syntax of C# and Visual Basic using the DLR, increasing comprehension dramatically. Other call invocation systems like Java’s Remote Method Invocation (RMI) can be mapped directly into our favorite languages as well, breathing life into existing code bases and increasing their overall business value. Because the DLR can shape the code and data of any other system into .NET so gracefully, the possibilities for using it should be limited only by your imagination.

Kevin Hazzard

&


CallSite Creation Optimization

Dynamic code has the potential of being slow so the DLR uses many performance techniques to speed things up. One of the simplest ideas is checking the existence of call sites as shown in Figure 2. Since the containers for call sites are static (Shared in Visual Basic), call sites only need to be created once, speeding up code that runs repeatedly and avoiding the expense altogether for dynamic code that may never run at all.



Listing 6: Return OData strongly-typed
XAttribute typeAttr = element.Attribute(
  XName.Get("type", metadataNamespace));
if (typeAttr != null)
{
  string type = typeAttr.Value;
  if (type != null)
  {
    switch (type)
    {
      default:
        break;
      case "Edm.Boolean":
        result =
          Convert.ToBoolean(result);
        break;
      case "Edm.Int32":
        result = Convert.ToInt32(result);
        break;
    }
  }
}


Listing 7: Enumerating eBay items
static void OnEbayItemsReady(dynamic ebayItems)
{
  Dump("eBay item information:");
  try
  {
    foreach (var item in ebayItems)
    {
      Dump("ID = {0}, Title ='{1}', " +
        "CurrentPrice = {2:C}",
        item.Id.Value,
        item.Title.Value.Substring(0, 20),
        item.CurrentPrice.Value);
    }
  }
  catch (Exception ex)
  {
    Dump("{0}: {1}", ex.GetType().Name,
      ex.Message);
  }
  Dump("Press Enter to continue ...");
}


Article Pages: < Previous - 1 2 3  4 

Page 1: Grokking the DLR: Why it’s Not Just for Dynamic Languages
Page 2: Dynamic Dispatch via Call Sites
Page 3: Managing Data Inside Your Dynamic Class
Page 4: Accessing the Dynamic Object as an Array

How would you rate the quality of this article?
1 2 3 4 5
Poor      Outstanding

Tell us why you rated the content this way. (optional)

Average rating:
4.3 out of 5

3 people have rated this article.

Xojo

      Component One

 

Learn Now