跨程序集边界返回/使用动态匿名类型

时间:2010-06-07 21:11:11

标签: c# .net dynamic anonymous-types

以下代码效果很好。如果GetUse方法位于不同的程序集中,则代码将失败并出现RuntimeBinderException。这是因为.Net运行时系统仅保证程序集内的匿名类型(在这种情况下为<string, int>)的通用性。

有没有办法愚弄运行时系统来克服这个问题?我可以在Use侧检查调试器中的对象,调试器可以看到相关的属性。

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 };
    }
}

5 个答案:

答案 0 :(得分:34)

使用ExpandoObject而不是匿名类型。这应该允许您安全地跨越装配边界:

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

    return person;
}

通常,匿名类型实际上只应在生成它们的同一方法中使用。一般来说,从方法中返回一个匿名类型会导致比它解决的更多问题。

答案 1 :(得分:8)

问题的原因是匿名类型是程序集内部的。这就是动态语言运行时不允许您访问其他程序集的属性的原因。

post解释了一种解决方案。您可以在程序集中放置一个自定义属性,以定义匿名类型,允许其他程序集访问其内部。

另一种解决方案是返回公共类的对象(具有公共属性)。当然,这会破坏匿名类型的优势。

第三种解决方案是使用 Reed Copsey 建议的ExpandoObject

如果您仍想使用匿名类型,您可以编写一个动态类来“装饰”任何匿名类型并公开其成员。这样的类必须实现IDynamicMetaObjectProvider接口并通过反射访问装饰对象。可能,这些东西已经由那里的人实施了。

答案 2 :(得分:1)

另一个好的解决方案可能是使用.Net 4中引入的元组:http://msdn.microsoft.com/en-us/library/dd268536.aspx

答案 3 :(得分:1)

这是一个穷人的解决方法; Newtonsoft.Json拯救,因为序列化往返生成动态类型实例,对您的/工作程序集可见。

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 ) ); }
}

答案 4 :(得分:0)

即兴接口

http://code.google.com/p/impromptu-interface/

允许您跨越边界使用匿名类型实例,但是您必须声明一个与其签名匹配的接口,或者至少要从其签名中访问该接口。