在c#中查找动态对象的类型

时间:2022-04-04 13:16:55

I have a list of dynamic objects. At runtime, I would like to find the type of objects in the list so that I can instantiate a new list of that type.

我有一个动态对象列表。在运行时,我想在列表中找到对象的类型,以便我可以实例化该类型的新列表。

List<dynamic> list1= new List<dynamic>() { new Test() {ID = 1} }

I would like to know that the ID is type int so I can use it in a Activator.CreateInstance statement. When I try to get the type using the following statement, I always get "object"

我想知道ID是int类型,所以我可以在Activator.CreateInstance语句中使用它。当我尝试使用以下语句获取类型时,我总是得到“对象”

Type typeInArgument = list1.GetType().GenericTypeArguments[0];

Is there a way to get this type? I saw some similar questions where the suggestion was to use

有没有办法获得这种类型?我看到了一些类似的问题,建议使用

Type unknown = ((ObjectHandle)list1).Unwrap().GetType();

But this doesn't compile for the List.

但这不会为List编译。

I need suggestions to resolve this.

我需要建议来解决这个问题。

2 个解决方案

#1


It sounds like it's working exactly as well as it possibly could.

听起来它的工作完全正常。

Because you're using dynamic, the greatest common denominator of list elements is object. Just because you happen only to have one element in there, that doesn't mean the runtime can guarantee that.

因为您使用的是动态,所以列表元素的最大公分母是对象。只是因为你只发生了一个元素,这并不意味着运行时可以保证。

As such, you probably have to special-case what you're looking for.

因此,你可能需要特殊情况下你正在寻找什么。

Type ret;
if (list1.Count == 0)
    ret = typeof(object);
else
    ret = list1[0].GetType();

Of course, that check is redundant if the code you've given us is meant to be taken literally. But I hope you see the point.

当然,如果你给我们的代码是字面上的,那么这个检查是多余的。但我希望你明白这一点。

You could also add in a check to run through the list and find if all items are the same type, if that's a requirement.

您还可以添加一个检查以运行列表,并查找是否所有项目都是相同的类型,如果这是一个要求。

In general, it sounds like this might not be a great time to use dynamic. If you need anonymous types, I'd suggest you move over to concrete ones for this. If you're doing what you're doing here, just type it as a List<Test>.

一般来说,听起来这可能不是使用动态的好时机。如果你需要匿名类型,我建议你转移到具体的类型。如果您正在执行此处所做的操作,只需将其键入List 即可。

Of course, if all you're looking for is essentially a clone of this list, you could do that and have it be right. I've done this as a foreach for readability, but LINQ would be a nice option here.

当然,如果您正在寻找的只是该列表的克隆,那么您可以做到这一点并使其正确。我已经将此作为可读性的foreach,但LINQ在这里是一个不错的选择。

List<object> ret = new List<object>();
foreach (var v in list1)
{
    var type = v.GetType();

    ret.Add(/* new instance of type */);
}
return ret;

Remember, of course, that this doesn't guarantee you anything more about the types contained, and you'll have pretty well the same issue again when you try and actually read the resultant list.

当然,请记住,这并不能保证您更多地了解所包含的类型,当您尝试并实际读取结果列表时,您将再次遇到相同的问题。

I would really suggest reevaluating your use of dynamic here. It does allow for some things that wouldn't otherwise be possible, so you might choose to stick with it, but it's worth a second thought.

我真的建议在这里重新评估你对动态的使用。它确实允许一些本来不可能的事情,所以你可能会选择坚持下去,但值得再考虑一下。

#2


A List<dynamic> doesn't have a specific inner type. The whole point of dynamic is that it can be anything.

List 没有特定的内部类型。动态的全部意义在于它可以是任何东西。

Instead, you can get the type of an item in the list: list1[0].GetType().
Note that there is no guarantee that the next item is of the same type.

相反,您可以获取列表中项目的类型:list1 [0] .GetType()。请注意,无法保证下一个项目属于同一类型。

#1


It sounds like it's working exactly as well as it possibly could.

听起来它的工作完全正常。

Because you're using dynamic, the greatest common denominator of list elements is object. Just because you happen only to have one element in there, that doesn't mean the runtime can guarantee that.

因为您使用的是动态,所以列表元素的最大公分母是对象。只是因为你只发生了一个元素,这并不意味着运行时可以保证。

As such, you probably have to special-case what you're looking for.

因此,你可能需要特殊情况下你正在寻找什么。

Type ret;
if (list1.Count == 0)
    ret = typeof(object);
else
    ret = list1[0].GetType();

Of course, that check is redundant if the code you've given us is meant to be taken literally. But I hope you see the point.

当然,如果你给我们的代码是字面上的,那么这个检查是多余的。但我希望你明白这一点。

You could also add in a check to run through the list and find if all items are the same type, if that's a requirement.

您还可以添加一个检查以运行列表,并查找是否所有项目都是相同的类型,如果这是一个要求。

In general, it sounds like this might not be a great time to use dynamic. If you need anonymous types, I'd suggest you move over to concrete ones for this. If you're doing what you're doing here, just type it as a List<Test>.

一般来说,听起来这可能不是使用动态的好时机。如果你需要匿名类型,我建议你转移到具体的类型。如果您正在执行此处所做的操作,只需将其键入List 即可。

Of course, if all you're looking for is essentially a clone of this list, you could do that and have it be right. I've done this as a foreach for readability, but LINQ would be a nice option here.

当然,如果您正在寻找的只是该列表的克隆,那么您可以做到这一点并使其正确。我已经将此作为可读性的foreach,但LINQ在这里是一个不错的选择。

List<object> ret = new List<object>();
foreach (var v in list1)
{
    var type = v.GetType();

    ret.Add(/* new instance of type */);
}
return ret;

Remember, of course, that this doesn't guarantee you anything more about the types contained, and you'll have pretty well the same issue again when you try and actually read the resultant list.

当然,请记住,这并不能保证您更多地了解所包含的类型,当您尝试并实际读取结果列表时,您将再次遇到相同的问题。

I would really suggest reevaluating your use of dynamic here. It does allow for some things that wouldn't otherwise be possible, so you might choose to stick with it, but it's worth a second thought.

我真的建议在这里重新评估你对动态的使用。它确实允许一些本来不可能的事情,所以你可能会选择坚持下去,但值得再考虑一下。

#2


A List<dynamic> doesn't have a specific inner type. The whole point of dynamic is that it can be anything.

List 没有特定的内部类型。动态的全部意义在于它可以是任何东西。

Instead, you can get the type of an item in the list: list1[0].GetType().
Note that there is no guarantee that the next item is of the same type.

相反,您可以获取列表中项目的类型:list1 [0] .GetType()。请注意,无法保证下一个项目属于同一类型。