dcsimg
 

Dynamic Objects in VB 2010

Monday Apr 26th 2010 by Paul Kimmel

Dynamic objects in VB let you bind data to members at runtime without defining a custom mapping class.

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.

Home
Mobile Site | Full Site
Copyright 2018 © QuinStreet Inc. All Rights Reserved