Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I access properties of an anonymous type returned from a function via the dynamic keyword?

I have a function that returns an anonymous type like so (simplified for illustrative purposes)...

public object GetPropertyInfo()
{
    return new {
        PropertyName = "Foo",
        Value = "Laa"
    };
}

When I do this...

dynamic pi = GetPropertyInfo();
Console.WriteLine(pi);

It outputs this (the same as if I did '?pi' in the immediate window)...

{ PropertyName = "A", Value = 44 }
    PropertyName: "A"
    Value: 44

But if I try doing this...

   string propertyName = pi.PropertyName;

...it compiles but throws a runtime exception saying

Exception thrown: 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' in System.Core.dll

Additional information: 'object' does not contain a definition for 'PropertyName'

What gives? What am I missing here?

like image 715
Mark A. Donohoe Avatar asked Aug 03 '15 03:08

Mark A. Donohoe


People also ask

When you define an anonymous type the compiler converts that type into a?

The compiler generates a name for each anonymous type. If two or more anonymous type objects are defined in the same assembly and the sequence of properties are same in terms of names and types than the compiler treats both as same object instances of type.

How to return list of anonymous type in c#?

Way 2: Handle by creating same anonymous type object o = AnonymousReturn(); var obj = Cast(o, new { Name = "", EmailID = "" }); Console. WriteLine(obj.Name + " " + obj. EmailID); In this way return value of the anonymous type is get assigned to object.

What is anonymous type of functions?

An anonymous type is a temporary data type that is inferred based on the data that we include in an object initializer. Properties of anonymous types are read-only in nature so cannot change their values. Let us try to change the value of Age.


3 Answers

The problem is that anonymous types are internal, which means that you can't access their properties with dynamic property accessors from projects other than the one they were created in. The dynamic binding treats them as the closest public inherited type it knows about--object.

To fix this, you can declare a public type to represent the values you're expecting to find in your anonymous type. This is probably a good idea anyway, since you're clearly expecting to consume the returned properties in other parts of your code. Using a declared type also enables you to maintain type-safety, avoiding the need for dynamic entirely.

If you absolutely must use dynamics here, the next best option is probably to change your AssemblyInfo.cs file to make internal properties accessible to the project you're trying to access them from:

[assembly:InternalsVisibleTo("MyOtherProject")]
like image 61
StriplingWarrior Avatar answered Sep 19 '22 17:09

StriplingWarrior


Edit

According to your edit. Apparently you are not required dynamic at all as there are no dynamic properties. Just create a concrete type with your predefined properties. It's better to avoid dynamic when possible anyway.

Old Answer

You need to use an ExpandoObject. Reference here.

In fact, GetPropertyInfo() should return an ExpandoObject.

    dynamic foo = this.GetPropertyInfo();
    string i = foo.MyPropertyName;

    private ExpandoObject GetPropertyInfo()
    {
        dynamic obj = new ExpandoObject();
        obj.PropertyName = "MyPropertyName";
        obj.PropertyType = "MyPropertyType";

        return obj;
    }

The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject.sampleMember instead of more complex syntax like sampleObject.GetAttribute("sampleMember").

like image 28
CharithJ Avatar answered Sep 20 '22 17:09

CharithJ


Also, you can use System.Reflection

object D = GetPropertyInfo(); 
Type t = D.GetType(); // get object's type
PropertyInfo p = t.GetProperty("PropertyName"); // look up for the property:
object P = p.GetValue(D, null); // get the value

Fiddle demo

like image 31
davcs86 Avatar answered Sep 20 '22 17:09

davcs86