如何使用反射将 IList 动态转换为任意数据类型的数组
how to dynamically cast IList to Array of an arbitrary datatype using Reflection
class myClass1
{
public string obj1;
public string obj2;
}
class myClass2
{
public myClass1[] fArray = new myClass1[1];
public string str;
}
class Program
{
static void Main(string[] args)
{
string mytype = "ConsoleApp3.myClass2";
Type type = Type.GetType(mytype);
object myObj = Activator.CreateInstance(type);
FieldInfo fi = type.GetField("fArray");
Type type2 = fi.FieldType.GetElementType();
object newObj;
IList list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(fi.GetValue(myObj).GetType().GetElementType()));
{
newObj = Activator.CreateInstance(type2);
FieldInfo fi2 = type2.GetField("obj1");
fi2.SetValue(newObj, "some txt1");
FieldInfo fi3 = type2.GetField("obj2");
fi3.SetValue(newObj, "some txt2");
list.Add(newObj);
}
{
newObj = Activator.CreateInstance(type2);
FieldInfo fi2 = type2.GetField("obj1");
fi2.SetValue(newObj, "some txt1");
FieldInfo fi3 = type2.GetField("obj2");
fi3.SetValue(newObj, "some txt2");
list.Add(newObj);
}
fi.SetValue(myObj, list.Cast<myClass1>().ToArray());
上面的代码运行良好。在我的用例中 "myClass1" 在编译时不知道。我在运行时收到 myClass1 的类型作为字符串。
如何使用反射将列表转换为 myClass1 类型的数组?
fi.SetValue(myObj, list.Cast<???>().ToArray());
您也可以创建泛型方法:
让我们为元素类型创建一个局部变量,以便我们可以重用它。
var elementType = fi.GetValue(myObj).GetType().GetElementType();
...
从linq可枚举中获取cast方法和数组方法class。
var castMethod = typeof(System.Linq.Enumerable).GetMethod("Cast").MakeGenericMethod(elementType);
var arrayMethod = typeof(System.Linq.Enumerable).GetMethod("ToArray").MakeGenericMethod(elementType);
使用 null 作为静态方法的第一个参数调用方法。
var casted = castMethod.Invoke(null, new[] { list });
var array = arrayMethod.Invoke(null, new[] { casted });
fi.SetValue(myObj, array);
可能有更聪明的方法来执行此操作,但这可能会让您入门。
Type.GetType and Type.MakeArrayType 来帮助你。
你可以这样做:
Type t = Type.GetType("myString");
或
Type arrayT = Type.GetType("myString").MakeArrayType() ;
在您的示例中,GetType
就足够了,但了解 MakeArrayType
也很好。
class myClass1
{
public string obj1;
public string obj2;
}
class myClass2
{
public myClass1[] fArray = new myClass1[1];
public string str;
}
class Program
{
static void Main(string[] args)
{
string mytype = "ConsoleApp3.myClass2";
Type type = Type.GetType(mytype);
object myObj = Activator.CreateInstance(type);
FieldInfo fi = type.GetField("fArray");
Type type2 = fi.FieldType.GetElementType();
object newObj;
IList list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(fi.GetValue(myObj).GetType().GetElementType()));
{
newObj = Activator.CreateInstance(type2);
FieldInfo fi2 = type2.GetField("obj1");
fi2.SetValue(newObj, "some txt1");
FieldInfo fi3 = type2.GetField("obj2");
fi3.SetValue(newObj, "some txt2");
list.Add(newObj);
}
{
newObj = Activator.CreateInstance(type2);
FieldInfo fi2 = type2.GetField("obj1");
fi2.SetValue(newObj, "some txt1");
FieldInfo fi3 = type2.GetField("obj2");
fi3.SetValue(newObj, "some txt2");
list.Add(newObj);
}
fi.SetValue(myObj, list.Cast<myClass1>().ToArray());
上面的代码运行良好。在我的用例中 "myClass1" 在编译时不知道。我在运行时收到 myClass1 的类型作为字符串。
如何使用反射将列表转换为 myClass1 类型的数组?
fi.SetValue(myObj, list.Cast<???>().ToArray());
您也可以创建泛型方法:
让我们为元素类型创建一个局部变量,以便我们可以重用它。
var elementType = fi.GetValue(myObj).GetType().GetElementType();
...
从linq可枚举中获取cast方法和数组方法class。
var castMethod = typeof(System.Linq.Enumerable).GetMethod("Cast").MakeGenericMethod(elementType);
var arrayMethod = typeof(System.Linq.Enumerable).GetMethod("ToArray").MakeGenericMethod(elementType);
使用 null 作为静态方法的第一个参数调用方法。
var casted = castMethod.Invoke(null, new[] { list });
var array = arrayMethod.Invoke(null, new[] { casted });
fi.SetValue(myObj, array);
可能有更聪明的方法来执行此操作,但这可能会让您入门。
Type.GetType and Type.MakeArrayType 来帮助你。
你可以这样做:
Type t = Type.GetType("myString");
或
Type arrayT = Type.GetType("myString").MakeArrayType() ;
在您的示例中,GetType
就足够了,但了解 MakeArrayType
也很好。