gpt4 book ai didi

c# - 如何使用 Activator.CreateInstance 创建运行时 T 未知的 List

转载 作者:行者123 更新时间:2023-11-30 19:35:43 25 4
gpt4 key购买 nike

我正在使用 Activator.CreateInstance通过类型变量(在运行时未知)创建对象:

static dynamic CreateFoo( Type t ) =>
Activator.CreateInstance( t );

显然,我还没有正确理解如何使用 dynamic类型,因为这仍然只是返回一个对象。

我需要能够将一个集合传递给另一个对 Activator.CreateInstance 的调用其中正在创建的类型可以是 List<T> :

var values = Enumerable.Range( 1, 50 ).Select(
I => CreateFoo( typeof( Foo ) ) ).ToArray( );
//This will explode.
var foobar = Activator.CreateInstance(
typeof( List<Foo> ), values );

调用上面的代码时,它会爆炸并出现以下异常:

enter image description here

我明白它为什么这样做了——当用类型参数定义列表时,没有期望可枚举对象的列表的构造函数。

问题是我无法转换对象,因为我不知道运行时的类型。 Activator.CreateInstance似乎只返回一个对象,这对 List<Foo> 没问题。因为我将使用依赖对象和属性来设置它们,所以盒装对象对它们来说非常好,但在尝试创建列表时会破坏所有内容(并且可能会破坏任何其他具有期望类型参数的构造函数的东西)。

我在这里尝试完成的事情的正确方法是什么?

符合Minimal, Complete and Verifiable Example要求:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MCVEConsole {
class Program {
static int Main( string[ ] args ) {
var values = Enumerable.Range( 1, 50 ).Select(
I => CreateFoo( typeof( Foo ) ) ).ToArray( );

//This will compile, but explode when run.
var foobar = Activator.CreateInstance(
typeof( List<Foo> ), values );
return 1;
}

static dynamic CreateFoo( Type t ) =>
Activator.CreateInstance( t );
}

class Foo {
public Foo( ) { }
}
}

最佳答案

使用这种方法:

class Program
{
static void Main(string[] args)
{
CreateListFromType(typeof(Foo));
CreateListFromType(typeof(int));
}

static object CreateListFromType(Type t)
{
// Create an array of the required type
Array values = Array.CreateInstance(t, 50);

// and fill it with values of the required type
for (int i = 0; i < 50; i++)
{
values.SetValue(CreateFooFromType(t), i);
}

// Create a list of the required type, passing the values to the constructor
Type genericListType = typeof(List<>);
Type concreteListType = genericListType.MakeGenericType(t);

object list = Activator.CreateInstance(concreteListType, new object[] { values });

// DO something with list which is now an List<t> filled with 50 ts
return list;
}


// Create a value of the required type
static object CreateFooFromType(Type t)
{
return Activator.CreateInstance(t);
}
}

class Foo
{
public Foo() { }
}

不需要使用dynamic在这种情况下。我们可以只使用 object为了我们创造的值(value)。非引用类型将存储在 object 中使用拳击。

为了创建List<>类型,我们可以首先获得通用类型的表示,然后使用它来使用 MakeGenericType 创建具体类型方法。

注意您在创建列表的 CreateInstance 调用中犯的错误:

尝试构建列表时,您需要将值数组作为一个元素嵌入到对象数组中。这样Activator将在 List<t> 中寻找构造函数期望类型为 IEnumerable<t> 的单个参数.

按照你写的方式,Activator寻找一个需要 50 个参数的构造函数,每个参数都是 t 类型。


使用非通用 IList 接口(interface)的较短版本

using System.Collections;

static IList CreateListFromType(Type t)
{
// Create a list of the required type and cast to IList
Type genericListType = typeof(List<>);
Type concreteListType = genericListType.MakeGenericType(t);
IList list = Activator.CreateInstance(concreteListType) as IList;

// Add values
for (int i = 0; i < 50; i++)
{
list.Add(CreateFooFromType(t));
}

// DO something with list which is now an List<t> filled with 50 ts
return list;
}

更接近实际用例:动态列表类型

static void Main(string[] args)
{
CreateListFromType(typeof(List<Foo>));
CreateListFromType(typeof(ObservableCollection<int>));
}

static IList CreateListFromType(Type listType)
{
// Check we have a type that implements IList
Type iListType = typeof(IList);
if (!listType.GetInterfaces().Contains(iListType))
{
throw new ArgumentException("No IList", nameof(listType));
}

// Check we have a a generic type parameter and get it
Type elementType = listType.GenericTypeArguments.FirstOrDefault();
if (elementType == null)
{
throw new ArgumentException("No Element Type", nameof(listType));
}

// Create a list of the required type and cast to IList
IList list = Activator.CreateInstance(listType) as IList;

// Add values
for (int i = 0; i < 50; i++)
{
list.Add(CreateFooFromType(elementType));
}

// DO something with list which is now a filled object of type listType
return list;
}

关于c# - 如何使用 Activator.CreateInstance 创建运行时 T 未知的 List<T>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52284671/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com