Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return/consume dynamic anonymous type across assembly boundaries

The code below works great. If the Get and Use methods are in different assemblies, the code fails with a RuntimeBinderException. This is because the .Net runtime system only guarantees commonality of anonymous types (<string, int> in this case) within assemblies.

Is there any way to fool the runtime system to overcome this? I can inspect the object in the debugger on the Use side, and the debugger can see the relevant properties.

class Program
{
    static void Main(string[] args)
    {
        UsePerson();
        Console.ReadLine();
    }

    public static void UsePerson()
    {
        var person = GetPerson();

        Console.WriteLine(person.Name);
    }

    public static dynamic GetPerson()
    {
        return new { Name = "Foo", Age = 30 };
    }
}
like image 584
friism Avatar asked Jun 07 '10 21:06

friism


4 Answers

Use an ExpandoObject instead of an anonymous type. This should allow you to cross assembly boundaries safely:

public static dynamic GetPerson() {     dynamic person = new ExpandoObject();     person.Name = "Foo";     person.Age = 30;      return person; } 

In general, anonymous types should really only be used within the same method in which they are generated. Returning an anonymous type from a method is, in general, going to cause more problems than it solves.

like image 69
Reed Copsey Avatar answered Oct 10 '22 14:10

Reed Copsey


The cause of the problem is that anonymous types are internal to assemblies. That's why the Dynamic Language Runtime don't allow you to access properties from another assembly.

One solution is explained in this post. You can put an custom attribute in the assembly that defines the anonymous type allowing the other assembly to access its internals.

Another solution is returning an object of a public class (with public properties). That will, of course, kill the advantages of the anonymous type.

A third solution would be using an ExpandoObject as suggested by Reed Copsey.

If you still want to use the anonymous type, you could write a dynamic class that "decorates" any anonymous type and exposes its members. Such a class would have to implement the IDynamicMetaObjectProvider interface and access the decorated object via reflection. Possibly, this stuff was already implemented by someone out there.

like image 27
jpbochi Avatar answered Oct 10 '22 16:10

jpbochi


Another good solution might be to use tuples, which were introduced in .Net 4: http://msdn.microsoft.com/en-us/library/dd268536.aspx

like image 21
friism Avatar answered Oct 10 '22 14:10

friism


Here's a poor man's workaround; Newtonsoft.Json to the rescue, as serialization roundtrip generates dynamic type instances visible to your/working assembly.

public static class TypeExt
{
  // roundtrip json serialization to enable access to dynamic members and properties originating from another assembly
  public static T JClone<T>( this T source ) { return JsonConvert.DeserializeObject<T>( JsonConvert.SerializeObject( source ) ); }
}
like image 25
gino.leovac Avatar answered Oct 10 '22 14:10

gino.leovac