Click here to Skip to main content
15,563,124 members
Articles / Programming Languages / C#
Tip/Trick
Posted 13 May 2020

Tagged as

Stats

22.5K views
210 downloads
8 bookmarked

Creating a Simple Dynamic Dictionary in C#

Rate me:
Please Sign up or sign in to vote.
2.86/5 (8 votes)
13 May 2020MIT2 min read
This tip shows how to create a dynamic JavaScript-like "object" to be used in web pages and T4 templates.
With this tip, I will demonstrate creating a JavaScript-like dynamic object in C# with arbitrary gettable and settable fields using .NET's DLR technology. This allows for readable and writable/creatable fields on arbitrary objects without having to create a strongly typed object. It is especially useful in ASP.NET pages and T4 templates to enhance readability and flexibility.

Use ExpandoObject instead: I thought it had been deprecated in .NET 1.x - I was mistaken

Introduction

JavaScript allows for the creation of objects simply by assigning values to arbitrary fields, creating them on the fly. There is no direct equivalent in C#. However, with the .NET DLR, we can create one. This can allow for more readable field access in cases where you would otherwise use a dictionary.

Conceptualizing this Mess

With Dictionary classes, you can get or set value by key, but if you're using them in ASP.NET pages, it can be somewhat clunky:

ASP.NET
<%= obj["foo"] %>

What we really want is:

ASP.NET
<%= obj.foo %>

Typically, C# will require you to use a strongly typed object instead of a dictionary for this, but that comes with two significant downsides: The first is it means extra coding. The second is you can't add arbitrary fields.

We're going to create a simple "object" that is backed by a dictionary with string keys. It will solve this problem by also allowing those name/values to be accessed using field accessing syntax.

You already know the upsides, but this approach has downsides as well that come in the form of marginally less performance than a dictionary and lack of compile-time type checking. You should use it when it will increase readability in certain circumstances where you would otherwise use a dictionary.

Coding this Mess

Since you already know how to use it from above, we'll focus on how I made it. The idea here is simple. We derive from DynamicObject and then implement a dictionary interface on top of it. All that does is override TryGetMember() and TrySetMember() and delegate to an inner dictionary. The dictionary members also forward to the inner dictionary. It's all very simple. I won't show all of the code, but I'll show the part that makes the magic of DynamicDictionary work:

C#
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
    T res;
    if (_inner.TryGetValue(binder.Name, out res))
    {
        result = res;
        return true;
    }
    result = null;
    return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
    _inner[binder.Name] = (T)value;
    return true;
}

Where T above is the type of values the dictionary holds - the key is always a string.

Using it is simple, and already described above but here's some of the example code - there's more in the included project, including a T4 template for demonstration purposes:

C#
// set some values
dynamic obj = new DynamicDictionary<object>();
obj.test1 = "foo";
obj["test2"] = "bar";
obj.test3 = 100;

// get some values
Console.WriteLine("test1 = " + obj.test1);
Console.WriteLine("test2 = " + obj["test2"]);
Console.WriteLine("test3 = " + obj["test3"]);

Note that above, both accessing as a dynamic object and as a dictionary are shown. These objects support either or, just like JavaScript. The magic here is the dynamic keyword, which tells the C# compiler to create a dynamic "call site" where member access is late bound - at runtime instead of compile time. Now you can simply access the object as usual, the exception being there is no Intellisense (autocompletion) in your IDE.

You can construct one of these dynamic objects in your codebehind, and then use them in your ASP.NET pages or T4 templates.

History

  • 13th May, 2020 - Initial submission

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
United States United States
Just a shiny lil monster. Casts spells in C++. Mostly harmless.

Comments and Discussions

 
QuestionIt has different usage than ExpandoObject Pin
Jacob Wakeem2-Sep-20 23:16
Jacob Wakeem2-Sep-20 23:16 
QuestionExpandoObject? Pin
TheFez625514-May-20 5:26
TheFez625514-May-20 5:26 
AnswerRe: ExpandoObject? Pin
Sacha Barber14-May-20 6:18
Sacha Barber14-May-20 6:18 
AnswerRe: ExpandoObject? Pin
honey the codewitch14-May-20 9:00
mvahoney the codewitch14-May-20 9:00 
GeneralRe: ExpandoObject? Pin
Sacha Barber14-May-20 21:12
Sacha Barber14-May-20 21:12 
GeneralRe: ExpandoObject? Pin
honey the codewitch14-May-20 21:38
mvahoney the codewitch14-May-20 21:38 
GeneralRe: ExpandoObject? Pin
Dmitry Mukalov15-May-20 6:11
Dmitry Mukalov15-May-20 6:11 
GeneralRe: ExpandoObject? Pin
honey the codewitch15-May-20 6:33
mvahoney the codewitch15-May-20 6:33 
GeneralRe: ExpandoObject? Pin
Dmitry Mukalov15-May-20 8:19
Dmitry Mukalov15-May-20 8:19 
Ok maybe, but your rhetoric in the previous post doesn't look like a question but rather as a conclusion.
GeneralRe: ExpandoObject? Pin
honey the codewitch15-May-20 10:13
mvahoney the codewitch15-May-20 10:13 
GeneralRe: ExpandoObject? Pin
Dmitry Mukalov15-May-20 20:17
Dmitry Mukalov15-May-20 20:17 
GeneralRe: ExpandoObject? Pin
honey the codewitch15-May-20 21:56
mvahoney the codewitch15-May-20 21:56 
GeneralRe: ExpandoObject? Pin
Dmitry Mukalov16-May-20 0:58
Dmitry Mukalov16-May-20 0:58 
GeneralRe: ExpandoObject? Pin
honey the codewitch16-May-20 5:24
mvahoney the codewitch16-May-20 5:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.