根据 ReturnType 转换 DynamicObject 的 属性 类型

Converting type of a property of a DynamicObject based on ReturnType

我在C#中有一个动态类型(Content,一个继承DynamicObject的类型)。它包装了一个包含数据的内部 JSON 对象。在 TryGetMember 中,我 return 从这个内部 JSON 对象请求的属性。这在简单类型(例如 int 或字符串 属性)的情况下工作得很好,因为 .Net 正确地转换了这些值。

但我想使用具有更复杂类型的属性:

dynamic content = Content.Load(id); 
IEnumerable<Book> bookList = content.Books;

问题是,在我的 class 的 TryGetMember 中,我无法知道我应该转换成的类型(在本例中为 IEnumerable Book),因为 binder.ReturnType 是 always Object。根据这篇文章,这是正常行为: Determining the expected type of a DynamicObject member access

但我觉得很难相信:API 怎么可能不让我知道目标类型?这样我将不得不强制开发人员使用方法语法来明确指定类型:

IEnumerable<Books> bookList = content.Books<IEnumerable<Book>>();

...又丑又怪

您可以将 Type 数据与 JSON 序列化数据一起存储,但这似乎是完成您尝试做的事情的一种相当低效的方法。如果您的内容不是 真正 动态的(例如,内容发生变化,但对象的基本架构是相同的),您可以为每个 classes 预编译JSON 对象类型,并在收到数据后将 JSON 序列化为 class。这样,编译器在运行时就可以识别所有类型数据。

事实证明,这确实是不可能的。我最终创建了一个 扩展方法 (以两种形式定义:用于动态集合和 JArray)。这样我至少可以获得我的内容的集合 class 并且以下所有解决方案都有效:

一行,但有点长

var members = ((IEnumerable<dynamic>)group.Members).ToContentEnumerable();    

单独的行

IEnumerable<dynamic> members = adminGroup.Members;
foreach (dynamic member in members.ToContentEnumerable())
{
    //...
}

使用扩展方法的方法调用语法(有点不寻常)。

var members = ContentExtensions.ToContentEnumerable(group.Members);