动态创建 IList 类型的新实例

发布于 2024-07-13 08:05:51 字数 387 浏览 4 评论 0原文

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

因此,在任何时候我都可能正在处理

IList<Customer> l;

,并且我想创建一个新的 Customer 实例

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

,然后将其添加到列表中。

l.Add(c);

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

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?

So at any one time I might be processing

IList<Customer> l;

and I'd like to create a new instance of 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

你的背包 2024-07-20 08:05:51

试试这个:

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

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);
    }
別甾虛僞 2024-07-20 08:05:51

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

    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 属性的类的基础。 如果需要,您可以使用接口而不是基类。

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.

弥枳 2024-07-20 08:05:51

您可以使用 Activator.CreateInstance方法通过其类型名称(作为字符串)或 System.Type 的实例调用类的构造函数。

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.

把梦留给海 2024-07-20 08:05:51

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

这是工厂的代码。

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

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();
}
天涯沦落人 2024-07-20 08:05:51

您可以使用 Type.GetGenericArguments 方法返回泛型类型 IList的类型参数。 然后调用适当的构造函数。

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

You could use the Type.GetGenericArguments method to return the type argument of the generic type IList<T>. Then invoke the appropriate constructor.

  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" } );
梦途 2024-07-20 08:05:51

是的,抱歉,我应该提到我将要处理的对象集将有一个接受 int 和字符串的构造函数。

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.

烟凡古楼 2024-07-20 08:05:51

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

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.

静若繁花 2024-07-20 08:05:51

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

var collectionType = targetList.GetType().GetProperty("Item").PropertyType;
var constructor = collectionType.GetConstructor(Type.EmptyTypes);
var newInstance = constructor.Invoke(null);

The best way to get the type of the IList is to look at the property type of the indexer!

var collectionType = targetList.GetType().GetProperty("Item").PropertyType;
var constructor = collectionType.GetConstructor(Type.EmptyTypes);
var newInstance = constructor.Invoke(null);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文