简体   繁体   English

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

[英]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. 如果GetUse方法位于不同的程序集中,则代码将失败并出现RuntimeBinderException。 This is because the .Net runtime system only guarantees commonality of anonymous types ( <string, int> in this case) within assemblies. 这是因为.Net运行时系统仅保证程序集内的匿名类型(在本例中为<string, int> )的通用性。

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. 我可以在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 };
    }
}

Use an ExpandoObject instead of an anonymous type. 使用ExpandoObject而不是匿名类型。 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. 一般来说,从方法中返回匿名类型会导致比它解决的问题更多的问题。

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 . 第三种解决方案是使用Reed Copsey建议的ExpandoObject

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. 这样的类必须实现IDynamicMetaObjectProvider接口并通过反射访问装饰对象。 Possibly, this stuff was already implemented by someone out there. 可能这个东西已经被那里的人实现了。

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

Here's a poor man's workaround; 这是一个穷人的解决方法; Newtonsoft.Json to the rescue, as serialization roundtrip generates dynamic type instances visible to your/working assembly. 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 ) ); }
}

impromptu-interface 即兴接口

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

Will let you use the the anonymous type instance across boundaries but you have to declare an interface that matches it's signature or at least what you want accessible from it's signature. 将允许您跨越边界使用匿名类型实例,但您必须声明一个与其签名匹配的接口,或者至少要从其签名中访问的接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM