DynamicExpresso icon indicating copy to clipboard operation
DynamicExpresso copied to clipboard

Cannot access anonymous class in properties of dynamic object

Open NielsUll opened this issue 6 years ago • 2 comments

Accessing a property of an anonymous class fails when going through a dynamic object:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : 'object' does not contain a definition for 'Foo'

[Test]
public void Get_Property_of_a_nested_anonymous()
{
    dynamic dyn = new ExpandoObject();
    dyn.Sub = new { Foo = "bar"};
    var interpreter = new Interpreter()SetVariable("dyn", (object)dyn);
    Assert.AreEqual(dyn.Sub.Foo, interpreter.Eval("dyn.Sub.Foo"));
}

It works fine when the class is named: dyn.Sub = new MyClass() { Foo = "bar"}; It also works if we introduce an intermediate variable:

    dynamic dyn = new ExpandoObject();
    dyn.Sub = new { Foo = "bar"};
    var interpreter = new Interpreter().SetVariable("dyn", dyn);
    interpreter.SetVariable("sub", interpreter.Eval("dyn.Sub"));
    Assert.AreEqual(dyn.Sub.Foo, interpreter.Eval("sub.Foo"));

Aslo discussed on stack overflow: https://stackoverflow.com/questions/53040955/how-can-i-use-dynamic-variables-with-anonymous-types

NielsUll avatar Oct 30 '18 08:10 NielsUll

Thanks @NielsUll Not sure when I can work on it, so any help is appreciated.

davideicardi avatar Oct 30 '18 17:10 davideicardi

In C#, anonymous types are internal types, which mean they're only visible to the assembly in which they're defined. In your scenario, the defining assembly (yours) is not the same as the DynamicExpresso assembly, which means the binder can't find its properties. There's a simple example here: https://stackoverflow.com/questions/2630370/c-sharp-dynamic-cannot-access-properties-from-anonymous-types-declared-in-anot .

You can see the same behavior when trying to use a private class as Sub:

[Test]
public void Get_Property_of_a_nested_internal_class()
{
	dynamic dyn = new ExpandoObject();
	dyn.Sub = new MyClass { Foo = "bar" };
	var interpreter = new Interpreter().SetVariable("dyn", (object)dyn);
	Assert.AreEqual(dyn.Sub.Foo, interpreter.Eval("dyn.Sub.Foo"));
}

private class MyClass
{
	public string Foo { get; set; }
}

If you change the class to be public instead, then the test pass.

Based on this analysis, I'm not sure this can be fixed in DynamicExpresso.

metoule avatar Jun 10 '21 15:06 metoule