Code below is working well as long as I have class ClassSameAssembly
in same assembly as class Program
.
But when I move class ClassSameAssembly
to a separate assembly, a RuntimeBinderException
(see below) is thrown.
Is it possible to resolve it?
using System;
namespace ConsoleApplication2
{
public static class ClassSameAssembly
{
public static dynamic GetValues()
{
return new
{
Name = "Michael", Age = 20
};
}
}
internal class Program
{
private static void Main(string[] args)
{
var d = ClassSameAssembly.GetValues();
Console.WriteLine("{0} is {1} years old", d.Name, d.Age);
}
}
}
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
: 'object' does not contain a definition for 'Name'
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at ConsoleApplication2.Program.Main(String[] args) in C:\temp\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 23
Here is a rudimentary version of an extension method for ToExpandoObject that I'm sure has room for polishing.
If you're already using Newtonsoft.Json in your project (or you're willing to add it for this purpose), you could implement that horrible extension method Jon Skeet is referring to in his answer like this:
I believe the problem is that the anonymous type is generated as
internal
, so the binder doesn't really "know" about it as such.Try using ExpandoObject instead:
I know that's somewhat ugly, but it's the best I can think of at the moment... I don't think you can even use an object initializer with it, because while it's strongly typed as
ExpandoObject
the compiler won't know what to do with "Name" and "Age". You may be able to do this:but that's not much better...
You could potentially write an extension method to convert an anonymous type to an expando with the same contents via reflection. Then you could write:
That's pretty horrible though :(
I ran into a similair problem and would like to add to Jon Skeets answer that there is another option. The reason I found out was that I realized that many extension methods in Asp MVC3 uses anonymous classes as input to provide html attributes (new {alt="Image alt", style="padding-top: 5px"} =>
Anyway - those functions use the constructor of the RouteValueDictionary class. I tried that myself, and sure enough it works - though only the first level (I used a multi-level structure). SO - in code this would be:
SO... What is really going on here? A peek inside the RouteValueDictionary reveals this code (values ~= o above):
SO - using TypeDescriptor.GetProperties(o) we would be able to get the properties and values despite the anonymous type being constructed as internal in a separate assembly! And of course this would be quite easy to extend to make it recursive. And to make an extension method if you wanted.
Hope this helps!
/Victor
ToExpando extension method (mentioned in Jon's answer) for the brave ones
You could use
[assembly: InternalsVisibleTo("YourAssemblyName")]
to make you assembly internals visible.