2

我的应用程序正在处理 IList 的。不同用户定义类型的 IList。我在想我可以使用反射来查看 IList 包含什么类型的对象,然后创建该类型的新实例,然后将其添加到 IList 本身?

所以在任何时候我都可能在处理

IList<Customer> l;

我想创建一个新的客户实例

Customer c = new Customer(0, "None")

然后将其添加到列表中

l.Add(c);

显然,在运行时动态地执行此操作是问题的症结所在。希望有人能给我一些指点。谢谢布伦丹

4

8 回答 8

4

试试这个:

    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);
    }

用法:

    IList<Customer> l = new List<Customer>();
    l.Add(new Customer(1,"Hi there ..."));

    AddNewElement(l, 0, "None");

(编辑):

那么试试这个:

    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);
    }
于 2009-02-04T13:52:38.510 回答
2

如果您可以使用无参数构造函数并在之后设置属性,那么您可以使您的方法成为通用方法,例如:-

    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);
    }

MyBase 是公开 int 和 string 属性的类的基础。如果需要,您可以使用接口而不是基类。

于 2009-02-04T13:38:10.660 回答
1

您可以使用该Activator.CreateInstance方法通过类的类型名称(作为字符串)或System.Type.

于 2009-02-04T13:38:10.990 回答
1

我认为你应该改变你的设计。您可以使用抽象工厂模式。使用反射会降低性能。

这是工厂的代码。

public abstract class MyStore {
    public abstract string Name { get; }
    public abstract void AddItem(int id, string name);
}

如果您的抽象类没有代码,您可以考虑使用接口。

然后创建客户商店。

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();
    }
}

用法

foreach (MyStore store in List<MyStore>)
    store.AddItem(0, "None");

如果您想考虑商店的类型,请使用

switch (store.Name) {
case "Customer Store":
    SomeMethod((CustomerStore)store);
    break;
default:
    throw new WhatEverException();
}
于 2009-02-04T15:35:28.193 回答
1

您可以使用 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" } );
于 2009-02-04T17:13:50.460 回答
0

这里最大的问题是:如果你不知道类型,你怎么知道如何制作一个新的?并非世界上的每种类型都有一个接受 int 和 string 的构造函数。

于 2009-02-04T13:31:52.657 回答
0

是的,对不起,我应该提到我将要处理的对象集将有一个接受 int 和 string 的构造函数。

于 2009-02-04T13:35:03.867 回答
0

获取 IList 类型的最佳方法是查看索引器的属性类型

var collectionType = targetList.GetType().GetProperty("Item").PropertyType;
var constructor = collectionType.GetConstructor(Type.EmptyTypes);
var newInstance = constructor.Invoke(null);
于 2010-12-27T06:34:48.600 回答