ExpandoObject object and GetProperty()
Asked Answered
B

1

5

I'm trying to write a generic utility for use via COM from outside .NET (/skip long story). Anyway, I'm trying to add properties to an ExpandoObject and I need to get PropertyInfo structure back to pass to another routine.

using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.Reflection;

public class ExpandoTest
{
    public string testThis(string cVariable)
    {
        string cOut = "";

        ExpandoObject oRec = new ExpandoObject { };
        IDictionary<string, object> oDict = (IDictionary<string, object>)oRec;

        oDict.Add(cVariable, "Test");

        Trace.WriteLine(cVariable);
        Trace.WriteLine(oDict[cVariable]);

        PropertyInfo thisProp = oRec.GetType().GetProperty(cVariable);

        if (thisProp != null)
        {
            cOut= "Got a property :)";
        }

        return cOut;
    }
}

Why do I always get a null in in thisProp? I clearly don't understand but I've been staring at it for a day and I'm not getting anywhere. All help/criticism thankfully accepted!

Beyond answered 31/8, 2015 at 13:16 Comment(4)
You're looking for a property of the ExpandoObject class itself. You won't get a PropertyInfo for a property you just made up (it doesn't exist, even if dynamic makes you think it does). Nothing's magical here. You could get a PropertyDescriptor though.Cacophony
I'm not sure what your use case is, but you may want to implement the IReflect interface. When used with COM interop this will allow you to implement a custom IDispatch interface. msdn.microsoft.com/en-us/library/…Anneliese
@LucasTrzesniewski All the examples of using ExpandoObject seem to do just that, even down to adding .GetValue(oRec, null) to the end (for example). @Anneliese I'm simply passing string parameters in through the COM interface (well, strings containing XML but still strings). It's being used to implement a user configurable text file importer (csv, tab delimited, etc.) but all the complexity is contained within .NET code. It's just not well defined data. I'm needing to build up a dynamic mapping for use with CsvHelper and I need to pass it PropertyInfo structures (using the example that I have)Beyond
@LucasTrzesniewski You're right. I went back and looked over all the articles that I've dug through and they were examples of uses of dynamic, not Expando. I was hoping that it decorated it somehow to add them as "virtual" properties but alas not. Thanks for the help.Beyond
R
11

While using an ExpandoObject it might look like you can add properties at runtime, it won't actually do that at the CLR level. That's why using reflection to get the property you added at runtime won't work.

It helps to think of an ExpandoObject as a dictionary mapping strings to objects. When you treat an ExpandoObject as a dynamic variable any invocation of a property gets routed to that dictionary.

dynamic exp = new ExpandoObject();
exp.A = "123";

The actual invocation is quite complex and involves the DLR, but its effect is the same as writing

((IDictionary<string, object>)exp)["A"] = "123";

This also only works when using dynamic. A strongly typed version of the code above results in a compile-time error.

var exp = new ExpandoObject();
exp.A = "123"; // compile-time error

The actual implementation of ExpandoObject can be found here.

Reposeful answered 31/8, 2015 at 13:42 Comment(1)
Thanks @dirk. I'll have to find another way to define the mapping.Beyond

© 2022 - 2024 — McMap. All rights reserved.