将动态转换为对象

7

这是我的代码:

MyClass here = new MyClass();
IEnumerable<MyClass> vats = (IEnumerable<MyClass>)here.All();

All()方法返回IEnumerable<dynamic>。我想将其转换为IEnumerable<MyClass>。上面那行代码不起作用,它说无法将类型为“d__15”的对象强制转换为类型“System.Collections.Generic.IEnumerable`1 [MyClass]”。

我还尝试过:

 IEnumerable<MyClass> vats = here.All() as IEnumerable<MyClass>;

但它返回null。


@Tigran 这是它。看看 Massive.cs 文件。https://github.com/robconery/massive - petko_stankoski
你的代码里不能保持“动态”的吗? - Delusional Logic
3个回答

6

与dbaseman的回答(以及AKX的评论)类似,我会使用Cast

IEnumerable<MyClass> vats = here.All().Cast<MyClass>();

不过,您需要使用using指令来处理LINQ:

using System.Linq;

在你的文件顶部加入“using”语句。如果无法识别“Select”方法,则说明你还没有添加该语句。
请注意,这假设每个值确实是“MyClass”引用。
编辑:如果想通过索引访问这些值,建议使用“ToList”。
List<MyClass> vats = here.All().Cast<MyClass>().ToList();

虽然 ToArray 也可以使用,但在大多数情况下,我个人更喜欢使用列表而不是数组,因为它们更加灵活。

编辑:听起来你的结果实际上充满了 ExpandoObject。你需要从每个项目创建一个新的 MyClass 实例,例如:

List<MyClass> vats = here.All()
                         .Select(item => new MyClass(item.Name, item.Value))
                         .ToList();

或者可能是:
List<MyClass> vats = here.All()
                         .Select(item => new MyClass {
                                     Name = item.Name,
                                     Value = item.Value,
                                 })
                         .ToList();

这只是一个例子,我不指望它能立即奏效 - 因为我们对于你的结果实际返回方式一无所知,所以我们无法做得更好。

恐怕你在这里已经超出了自己的能力范围。


我的值在哪里可以找到?比如vats[0],vats[1]。在这里的结果中,我可以像这样访问这些值。 - petko_stankoski
@Srcee:您可以从序列中迭代您的值,但如果您想要一个索引器,您需要一个列表或数组。但看起来您对C#和LINQ还比较新-在这种情况下,如果可能的话,我建议您暂时远离动态类型...这会使理解基础知识更加困难... - Jon Skeet
@RuneFS:当涉及到动态类型时,情况会变得更糟糕 - 但考虑到其他评论,我怀疑在这种特殊情况下最好不要深入讨论这个问题...因为我怀疑这会进一步困惑提问者。 - Jon Skeet
@RuneFS:将其转换为列表比转换为数组更有效,因为您不需要最终得到确切大小的数组 :) 当然,您可以将列表或数组包装为不可变列表。 - Jon Skeet
我相信效率可以忽略不计,因为最坏的情况是释放额外分配的空间(在使用列表时可以忽略)。我对你说的一切都没有异议。我只是觉得有趣的是,基于相同的论点但对不同方面的重视不同,我们却站在了相反的阵营。显然,你更看重未来的灵活性,而我则尽量保持我代码所依赖的接口尽可能狭窄,并且并不真正担心我现在不需要的灵活性(或者预计在不久的将来也不会使用)。 - Rune FS
显示剩余6条评论

1

您只需对每个单独的对象进行转换:

MyClass[] vats = here.All().Select(item => (MyClass)(dynamic)item).ToArray();

@Scree 再次编辑。我认为这就是你要找的——要使用方括号表示法,它必须是一个数组或列表。 - McGarnagle
@dbaseman 我收到了错误信息“无法将类型'System.Dynamic.ExpandoObject'转换为'MyClass'”。 - petko_stankoski
@Scree 哦...它是一个ExpandoObject。我又编辑了一次我的答案,那个应该可以用了。:P - McGarnagle
@Scree,我被难住了。我可以使用那段代码从ExpandoObject中进行转换。 - McGarnagle
@Srcee:你打算如何从ExpandoObject构建一个MyClass?我们不知道你的数据是如何返回的。 - Jon Skeet
显示剩余6条评论

0
在创建解决方案之前需要确定的第一件事是运行时对象将具有哪些类型。从您的评论中可以看出,它们将是ExpandoObjects,并假设MyClass不派生自ExpandoObject,因此您无法使用`.Cast< T >`方法,因为它仅支持转换而不支持自定义转换。
您可以使用 JavaScriptSerializer 进行从ExpandoObjects的转换的技巧。
从这里 link 中使用扩展方法,您可以使用它。
public static IEnumerable<T> Convert<T>(this IEnumerable<dynamic> self){
    var jsSerializer = new JavaScriptSerializer();
    foreach(var obj in self){
        yield return jsSerializer.ConvertToType<T>(obj);
    }
}

在您的情况下,您所要做的就是将Skeet的答案中的Cast更改为Convert。
List<MyClass> vats = here.All().Convert<MyClass>().ToList();

这有点hackish,因为JavaScriptSerializer并不是为此而设计的,但它确实解决了问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接