Динамическое создание нового экземпляра типа IList - PullRequest
2 голосов
/ 04 февраля 2009

Мое приложение обрабатывает IList. Списки различных пользовательских типов. Я думаю, что я могу использовать отражение, чтобы увидеть, какой тип объекта содержит IList, а затем создать новый экземпляр этого типа и затем добавить его в сам IList?

Так что в любой момент я мог бы обрабатывать

IList<Customer> l;

и я хотел бы создать новый экземпляр Customer

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

и затем добавьте это в список

l.Add(c);

Очевидно, что делать это динамически во время выполнения - вот суть проблемы. Надеюсь, кто-нибудь может дать мне несколько советов. Спасибо, Брендан

Ответы [ 8 ]

4 голосов
/ 04 февраля 2009

Попробуйте это:

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

(EDIT):

Попробуйте это тогда:

    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);
    }
2 голосов
/ 04 февраля 2009

Если вы можете использовать конструктор без параметров и установить свойства впоследствии, вы можете сделать ваш метод универсальным, например: -

    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. Вы можете использовать интерфейс, а не базовый класс, если хотите.

1 голос
/ 04 февраля 2009

Вы можете использовать метод 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" } );
1 голос
/ 04 февраля 2009

Я думаю, вы должны изменить свой дизайн. Вы можете использовать абстрактный шаблон фабрики . Использование отражения ухудшит производительность.

Вот код для фабрики.

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();
}
1 голос
/ 04 февраля 2009

Вы можете использовать метод Activator.CreateInstance для вызова конструктора для класса через имя его типа (в виде строки) или экземпляр System.Type.

0 голосов
/ 27 декабря 2010

Лучший способ получить тип IList - посмотреть на тип свойства индексатора !

var collectionType = targetList.GetType().GetProperty("Item").PropertyType;
var constructor = collectionType.GetConstructor(Type.EmptyTypes);
var newInstance = constructor.Invoke(null);
0 голосов
/ 04 февраля 2009

Да, извините, я должен был упомянуть, что набор объектов, которые я буду обрабатывать, будет иметь конструктор, который принимает int и строку.

0 голосов
/ 04 февраля 2009

Большая проблема здесь: если вы не знаете тип, как вы знаете, как сделать новый? Не у каждого типа в мире есть конструктор, который принимает int и строку.

...