Adding unknown (at design time) properties to an ExpandoObject
Asked Answered
S

5

51

just exploring c# 4. Trying to get my head around all this dynamic stuff. Sorry if this question is silly, no experience in this domain.

If I have an ExpandoObject and want to add public properties (with get and set) to it at runtime, how would I go about doing it?

For example, I have a documentTemplate and a document, which has a property pointing towards the documentTemplate. This documentTemplate has got some tag Titles (eg. Capabilities developed among students), which should be addressed while making the document (eg. Concentration, memory etc.). So as soon as the template is set in the document, I want to create a class, which has properties with same names as the tag titles in the Template, and then using some UI element, such as the PropertyGrid, I can have the user fill in tag values against the tag Titles.

Thanks for reading!

Sikorski answered 4/6, 2010 at 12:22 Comment(1)
Just wanted to add that I read the dead-tree edition of this article on ExpandoObject: msdn.microsoft.com/en-us/magazine/ff796227.aspx Not sure if it answers your questions, but it was a great primery for me.Fabric
F
101

I wondered how it might be possible to add members to a class "on the fly" and came up with this sample:

using System;
using System.Collections.Generic;
using System.Dynamic;

class Program
{
    static void Main()
    {
        dynamic expando = new ExpandoObject();
        var p = expando as IDictionary<String, object>;

        p["A"] = "New val 1";
        p["B"] = "New val 2";

        Console.WriteLine(expando.A);
        Console.WriteLine(expando.B);
    }
}

The point of this code snippet is that the members A and B are defined as string literals (hard coded/stringified) in and added via ExpandoObject's IDictionary interface. We test for the keys' existence and values (and prove the concept) by accessing them directly and outputting to console.

Finnic answered 22/8, 2010 at 5:57 Comment(2)
Cannot apply indexing with [] to an expression of type 'System.Dynamic.ExpandoObject'. Any ideas?Mannerism
@JasonFoglia: Yes. Please post this as a question and show some code including input and expected output. We can only guess at what might be going on from a comment...Finnic
L
4

It's possible to add delegate properties to an ExpandoObject, which then act (almost) just like methods. e.g.,

dynamic obj = new ExpandoObject();
obj.GetDocumentTemplate = () => { ... };
...
obj.GetDocumentTemplate(); // invokes delegate
Lavernlaverna answered 4/6, 2010 at 14:0 Comment(0)
A
3

Yes, ExpandoObject is very much designed to dynamically add properties to a "property bag". The notion of giving such a property an getter and setter is not supported however. Maybe that's clear if you think about it a bit: it wouldn't be a dynamic property anymore if you already know what the getter and setter should do. The closest you could get is implementing the INotifyPropertyChanged event so you can detect changes. Some sample code:

using System;
using System.Dynamic;
using System.ComponentModel;

class Program {
  static void Main(string[] args) {
    dynamic obj = new ExpandoObject();
    obj.test = 42;     // Add a property
    Console.WriteLine(obj.test);

    var inpc = (INotifyPropertyChanged)obj;
    inpc.PropertyChanged += inpc_PropertyChanged;
    obj.test = "foo";
    Console.ReadLine();
  }

  static void inpc_PropertyChanged(object sender, PropertyChangedEventArgs e) {
    Console.WriteLine("'{0}' property changed", e.PropertyName);
  }

}
Analogical answered 4/6, 2010 at 13:39 Comment(3)
Thanks for the explanation and code Hans. However, my query is slightly different. I want to know that is it possible to add the "test" property at runtime? I mean we don't even know the property name at design time. Something like: obj.SetProperty(stringVariable) = anotherStringVariable.Sikorski
Erm, no. Why don't you simply use a Dictionary<string, dynamic>?Analogical
So that I can easily bind to Windows Forms UISikorski
L
3

I just discovered this interesting fact: XAML Bindings to an ExpandoObject will also create the properties the binding is trying to access.

I still need more creativity to find out what this could be good for. Dynamic object creation on the UI? sounds cool :D I will try something out.

Lieselotteliestal answered 4/8, 2011 at 17:32 Comment(1)
You're sadistic :-)Sheepcote
F
2

The answers so far cover the basics quite well, but I felt this MSDN Magazine article was worth sharing as well:

http://msdn.microsoft.com/en-us/magazine/ff796227.aspx

It covers some examples of using dynamic XML input to dynamically create and use ExpandoObjects.

Fabric answered 4/11, 2010 at 19:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.