Dynamic Objects in VB 2010

Introduction

Riddle: When is an object not an object? When it is a dynamic object. Well, not really. Dynamic objects are a mechanism for mapping class-like object behavior and binding at runtime. The short of it is that you have something you want to treat like an instance of a pre-defined class without having the pre-defined class, just the data.

The first scenario that comes to mind is legacy type data. Suppose you have some text data representing legacy data. Further suppose that the text data contains name and value pairs. In the past you would have to sift through the data, map a custom class to the names, and then parse the data populating the custom objects. Well, dynamic objects sort of let you define the mapping scenario without necessarily defining the custom class. Instead you define a child class that inherits from System.Dynamic.DynamicObject and write code that describes how to make sense of the data. Then, you treat instances of the dynamic objects as if they were the instances of the (non-existent) custom class using member of (.) syntax.

The underlying data can be something is simple as a string, a text file, or an XML file. The result is that your write code like object.member and the DynamicObject plumbing binds the member name dynamically (or, at runtime, if you will).

Defining a Simple DynamicObject

To define a DynamicObject in VB define a new class that inherits from System.Dynamic.DynamicObject. Override one of the many available members based on how or what you want to invoke at runtime. For instance override TryGetMember to get member properties. TryGetMember accepts a GetMemberBinder parameter, a ByRef result that represents the return data, and returns a Boolean indicating success or failure. Listing 1 contains a DynamicObject, SimpleObject that overrides TryGetMember and looks for GetBinderMember.Name values of Name, Street, City_State.

Public Class SimpleObject
    Inherits DynamicObject

    Property Data As String()

    Public Sub New(ByVal Data() As String)
      Me.Data = Data
    End Sub

    Public Overrides Function TryGetMember(ByVal binder As GetMemberBinder,
                                       ByRef result As Object) As Boolean

      Dim item = (From one In Data
                 Where one.Contains(binder.Name)
                 Select one).First()
      
      If binder.Name = "Name" Then
          result = item.Replace("Name: ", "")
          Return True
      ElseIf binder.Name = "Street" Then
          result = item.Replace("Street: ", "")
          Return True
      ElseIf binder.Name = "City_State" Then
          result = item.Replace("City_State: ", "")
          Return True
      End If
      Return False
    End Function
End Class

Listing 1: SimpleObject is a DynamicObject that looks for simple string field values

SimpleObject is initialized with an array of strings containing Name, Street, and City_State data. When an instance of SimpleObject accesses a field at runtime, like SimpleObject.Name, TryGetMember will parse, find the correct string and parse out the "Name: " part returning the data part.

Using a DynamicObject in VB

To use SimpleObject think of it as any other kind of instance of a class. Initialize it with the correct parameters and invoke members as if they were early bound members. The DynamicObject plumbing will resolve the member access.

Listing 2 contains all of the code for the sample. The Module demonstrates how to use SimpleObject.

In the Listing there are two arrays of strings that we want to treat like objects. The Main function initializes two instances of SimpleObject, one for each array of strings. All that is left to do is access the data using member-of (.) syntax. For example, the SimpleObject paul can access Name, Street, and City_State using the same syntax as if there were properties with these names.

Imports System.Dynamic

Public Class SimpleObject
    Inherits DynamicObject

    Property Data As String()

    Public Sub New(ByVal Data() As String)
      Me.Data = Data
    End Sub

    Public Overrides Function TryGetMember(ByVal binder As GetMemberBinder,
                                       ByRef result As Object) As Boolean

      Dim item = (From one In Data
                 Where one.Contains(binder.Name)
                 Select one).First()
      
      If binder.Name = "Name" Then
          result = item.Replace("Name: ", "")
          Return True
      ElseIf binder.Name = "Street" Then
          result = item.Replace("Street: ", "")
          Return True
      ElseIf binder.Name = "City_State" Then
          result = item.Replace("City_State: ", "")
          Return True
      End If
      Return False
    End Function
End Class

Module Module1
    Dim data() As String =
      {"Name: Paul Kimmel",
       "Street: 1313 Mockingbord Ln.",
       "City_State: Flostinspace. MI 55555"}

    Dim data2() As String =
      {"Name: Joe Kunk",
       "Street: 1313 Stargazer Way",
       "City_State: Flostinspace. MI 55555"
       }


    Sub Main()
        Dim paul As Object = New SimpleObject(data)
        Console.WriteLine(paul.Name)
        Console.WriteLine(paul.Street)
        Console.WriteLine(paul.City_State)

        Dim joe As Object = New SimpleObject(data2)
        Console.WriteLine(joe.Name)
        Console.WriteLine(joe.Street)
        Console.WriteLine(joe.City_State)
        Console.ReadLine()
    End Sub
End Module

Listing 2: Initialize SimpleObject with an array of strings but treat it (in this case) as if it had pre-defined Name, Street, and City_State properties.

Summary

Historically when programmers encountered legacy data, strings or XML some kind of code had to be written to parse and populate that data into custom objects. You can still do that of course. You also have the option to use LINQ to XML and a project-select clause-to access the data or you can use DynamicObjects in VS2010.

A DynamicObject uses late binding to let you treat data elements as fully qualified members of a class. There is no mapped class just mapping behaviors if you will. It will be interesting to see how DynamicObjects and late binding make their way into the lexicon of programming techniques.



About the Author

Paul Kimmel

Paul Kimmel is the VB Today columnist for CodeGuru and has written several books on object-oriented programming and .NET. Check out his upcoming book Professional DevExpress ASP.NET Controls (from Wiley) now available on Amazon.com and fine bookstores everywhere. Look for his upcoming book Teach Yourself the ADO.NET Entity Framework in 24 Hours (from Sams). You may contact him for technology questions at pkimmel@softconcepts .com. Paul Kimmel is a Technical Evangelist for Developer Express, Inc, and you can ask him about Developer Express at paulk@devexpress.com and read his DX blog at http:// community.devexpress.com/blogs/paulk.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

Most Popular Programming Stories

More for Developers

RSS Feeds