C# 动态创建 IList 类型的新实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/511315/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dynamically creating a new instance of IList's type
提问by user48408
My application is processing IList's. ILists of different user defined types. I'm thinking that i can use reflection to to see what type of object the IList contains and then create a new instance of that type and subsequently add that to the IList itself?
我的应用程序正在处理 IList。不同用户定义类型的 ILists。我在想我可以使用反射来查看 IList 包含什么类型的对象,然后创建该类型的新实例,然后将其添加到 IList 本身?
So at any one time I might be processing
所以在任何时候我都可能正在处理
IList<Customer> l;
and I'd like to create a new instance of Customer
我想创建一个新的 Customer 实例
Customer c = new Customer(0, "None")
and then add that onto the list
然后将其添加到列表中
l.Add(c);
Obviously doing this dynamically at run-time is the crux of the problem. Hope somebody can give me some pointers. Thanks brendan
显然,在运行时动态执行此操作是问题的关键。希望有人能给我一些指点。谢谢布兰登
采纳答案by bruno conde
Try this:
尝试这个:
public static void AddNewElement<T>(IList<T> l, int i, string s)
{
T obj = (T)Activator.CreateInstance(typeof(T), new object[] { i, s });
l.Add(obj);
}
Usage:
用法:
IList<Customer> l = new List<Customer>();
l.Add(new Customer(1,"Hi there ..."));
AddNewElement(l, 0, "None");
(EDIT):
(编辑):
Try this then:
然后试试这个:
public static void AddNewElement2(IList l, int i, string s)
{
if (l == null || l.Count == 0)
throw new ArgumentNullException();
object obj = Activator.CreateInstance(l[0].GetType(), new object[] { i, s });
l.Add(obj);
}
回答by mqp
The big problem here is: If you don't know the type, how do you know how to make a new one? Not every type in the world has a constructor that takes an int and a string.
这里的大问题是:如果你不知道类型,你怎么知道如何制作一个新的?并非世界上的每种类型都有一个接受 int 和 string 的构造函数。
回答by user48408
Yes sorry i should have mentioned that the set of objects i will be processing will have a constructor that accepts an int and a string.
是的,抱歉,我应该提到我将要处理的对象集将有一个接受 int 和 string 的构造函数。
回答by Adam Ralph
If you can use a parameterless constructor and set the properties afterwards then you can make your method generic, something like:-
如果您可以使用无参数构造函数并在之后设置属性,那么您可以使您的方法通用,例如:-
void Process<T>(IList<T> list, int x, string y) where T : MyBase, new()
{
T t = new T();
t.X = x;
t.Y = y;
list.Add(t);
}
Where MyBase is the base for your classes which expose the int and string properties. You can use an interface rather than a base class if you want.
其中 MyBase 是公开 int 和 string 属性的类的基础。如果需要,您可以使用接口而不是基类。
回答by Konrad Rudolph
You can use the Activator.CreateInstance
method to invoke a constructor for a class via its type name (as a string) or an instance of System.Type
.
您可以使用该Activator.CreateInstance
方法通过类的类型名称(作为字符串)或 的实例调用类的构造函数System.Type
。
回答by Chaowlert Chaisrichalermpol
I think you should change your design. You can use abstract factory pattern. Using reflection would degrade performance.
我认为你应该改变你的设计。您可以使用抽象工厂模式。使用反射会降低性能。
Here is code for factory.
这是工厂的代码。
public abstract class MyStore {
public abstract string Name { get; }
public abstract void AddItem(int id, string name);
}
You can consider using interface if your abstract class has no code.
如果您的抽象类没有代码,您可以考虑使用接口。
Then create Customer store.
然后创建客户商店。
public class CustomerStore : MyStore, IEnumerable<Customer> {
List<Customer> list = new List<Customer>();
public override string Name { get { return "Customer Store"; } }
public override void AddItem(int id, string name) {
list.Add(new Customer(id, name));
}
public IEnumerator<Customer> GetEnumerator() {
return list.GetEnumerator();
}
}
Usage
用法
foreach (MyStore store in List<MyStore>)
store.AddItem(0, "None");
If you want to consider type of store, use
如果您想考虑商店类型,请使用
switch (store.Name) {
case "Customer Store":
SomeMethod((CustomerStore)store);
break;
default:
throw new WhatEverException();
}
回答by baretta
You could use the Type.GetGenericArguments method to return the type argument of the generic type IList<T>. Then invoke the appropriate constructor.
您可以使用 Type.GetGenericArguments 方法返回泛型类型 IList<T> 的类型参数。然后调用适当的构造函数。
Type T = l.GetType ( ).GetGenericArguments ( ) [ 0 ];
ConstructorInfo ctor = T.GetConstructor (
new Type [ 2 ] { typeof ( int ), typeof ( string ) } );
System.Diagnostics.Debug.Assert ( ctor != null );
object instance = ctor.Invoke (
new object [ 2 ] { 0, "None" } );
回答by Bryan Legend
The best way to get the type of the IList is to look at the property type of the indexer!
获得 IList 类型的最好方法是查看索引器的属性类型!
var collectionType = targetList.GetType().GetProperty("Item").PropertyType;
var constructor = collectionType.GetConstructor(Type.EmptyTypes);
var newInstance = constructor.Invoke(null);