• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 93
  • Last Modified:

Expando

I have no practical experience of using Expando having only read about it.  I have a few questions if someone could aid me please?

1. Can I declare an Expando object then make it equal to another object and then add new properties?
2. Can I dynamically add an interface to an Expando object so it can be consumed later as that interface?  A small explanation here,I like to use Interface types in collections, I find it easier to maintain and extend code.
0
Alyanto
Asked:
Alyanto
  • 3
1 Solution
 
it_saigeDeveloperCommented:
An ExpandoObject is a dynamic object.  The ExpandoObject works by implementing an IDictionary<string, object> (C#) [or IDictionary(Of String, Object) (VB.NET)].

Understanding this, the answer to your first question is yes.

Proof of concept:

In C# -
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;

namespace EE_Q28982492
{
	class Program
	{
		static void Main(string[] args)
		{
			Person john = new Person() { ID = 1, FirstName = "John", Birthdate = new DateTime(1984, 02, 16) };
			dynamic clone = john.ToDynamic();
			clone.LastName = "Jones";
			clone.Age = string.Format("{0} year{1}", DateTime.Now.Year - clone.Birthdate.Year, (DateTime.Now.Year - clone.Birthdate.Year) == 1 ? " old" : "s old");

			Console.WriteLine("Properties for John -");
			foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(john.GetType()))
				Console.WriteLine("{{ Name = {0}, Value = {1} }}", property.Name, property.GetValue(john));

			Console.WriteLine("Properties for John's Clone -");
			foreach (KeyValuePair<string, object> pair in (IDictionary<string, object>)clone)
				Console.WriteLine("{{ Name = {0}, Value = {1} }}", pair.Key, pair.Value);

			Console.ReadLine();
		}
	}

	class Person
	{
		public int ID { get; set; }
		public string FirstName { get; set; }
		public DateTime Birthdate { get; set; }
	}

	static class Extensions
	{
		public static dynamic ToDynamic<T>(this T value)
		{
			IDictionary<string, object> expando = new ExpandoObject();
			foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(typeof(T)))
				expando.Add(property.Name, property.GetValue(value));
			return expando as ExpandoObject;
		}
	}
}

Open in new window


In VB.NET -
Imports System.Dynamic
Imports System.ComponentModel

Module Module1
	Sub Main()
		Dim john As New Person() With {.ID = 1, .FirstName = "John", .Birthdate = New DateTime(1984, 2, 16)}
		Dim clone As Object = john.ToDynamic()
		clone.LastName = "Jones"
		clone.Age = String.Format("{0} year{1}", DateTime.Now.Year - clone.Birthdate.Year, If((DateTime.Now.Year - clone.Birthdate.Year) = 1, " old", "s old"))

		Console.WriteLine("Properties for John -")
		For Each [property] As PropertyDescriptor In TypeDescriptor.GetProperties(john.[GetType]())
			Console.WriteLine("{{ Name = {0}, Value = {1} }}", [property].Name, [property].GetValue(john))
		Next

		Console.WriteLine("Properties for John's Clone -")
		For Each pair As KeyValuePair(Of String, Object) In DirectCast(clone, IDictionary(Of String, Object))
			Console.WriteLine("{{ Name = {0}, Value = {1} }}", pair.Key, pair.Value)
		Next

		Console.ReadLine()
	End Sub
End Module

Class Person
	Public Property ID() As Integer
	Public Property FirstName() As String
	Public Property Birthdate() As DateTime
End Class

Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Function ToDynamic(Of T)(value As T) As ExpandoObject
		Dim expando As IDictionary(Of String, Object) = New ExpandoObject()
		For Each [property] As PropertyDescriptor In TypeDescriptor.GetProperties(GetType(T))
			expando.Add([property].Name, [property].GetValue(value))
		Next
		Return TryCast(expando, ExpandoObject)
	End Function
End Module

Open in new window


Each of which produce the following output -Capture.JPG
The very nature of the expando object makes your second question irrelevant because it can be anything.  If you are going to use an interface, this requires static typing which is counter-intuitive to the expando object which is dynamic.

-saige-
2
 
AlyantoAuthor Commented:
Hi it_saige
In the mean time I had arrived at about the point you demonstrate here.  What I am working on is mediator pattern in WPF.  The problem is to do with control collision so I am working with UIElements.  I was thinking rather than write a new class, translate the information from the various child UIElements on the panel into a collection of this new class I could use ExpandoObject to inherit the current child add new properties and implement and interface and an abstract class.

so for me this is the abstract subscriber and an interface called ISubscriptionMembership (add and remove subscription)

I am doing some feasibility of doing this which is where this question comes from, best to not count my chickens before they hatch.

/Aly
0
 
AlyantoAuthor Commented:
Added a follow on question, please take a look.
0
 
AlyantoAuthor Commented:
On the button, many thanks.
0

Featured Post

Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now