Динамическое создание нового экземпляра типа IList в

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

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

IList<Customer> l;

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

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

а затем добавить, что на список

l.Add(c);

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


person user48408    schedule 04.02.2009    source источник
comment
Подсказка Вы должны указать свой Ланг я думаю, его в C #, но она должна быть там, где некоторые ....   -  person Peter    schedule 04.02.2009
comment
да, я просто понял, что при просмотре постановки вопроса сам, спасибо   -  person user48408    schedule 04.02.2009


Ответы (8)


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

    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);
    }
person bruno conde    schedule 04.02.2009
comment
Я думаю, что это сработает, но способ обработки списков не позволяет этого сделать. то есть foreach (IList l in arrayOfPopulatingLists) { AddNewElement(l, 0, None) } // Ошибка компилятора: Аргументы для метода не могут быть выведены из использования. Нужно ли мне изучать вызов универсальных методов? - person user48408; 04.02.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 является базой для классов, которые обнажают ИНТ и строковые свойства. Вы можете использовать интерфейс, а не базовый класс, если вы хотите.

person Adam Ralph    schedule 04.02.2009
comment
Этот код не работает, и нет ничего подобного для достижения этого эффекта. - person Konrad Rudolph; 04.02.2009
comment
К сожалению, вы правы, редактировал пост соответственно. Спасибо - person Adam Ralph; 04.02.2009
comment
Это выглядит хорошо. С точки зрения использования. У меня есть массив IList, который я обрабатываю в foreach. Итак, foreach(IList l in arrayOfILists) { Process(l, 0, None); } не собирается компилироваться, что является новым для дженериков, я не понимаю, почему бы и нет (?) - person user48408; 04.02.2009
comment
Значит, вы хотите воздействовать на неуниверсальный IList? В своем вопросе вы сказали, что вы хотите, чтобы действовать на родовом IList давая IList в качестве примера. - person Adam Ralph; 04.02.2009

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

person Konrad Rudolph    schedule 04.02.2009
comment
Проблема здесь в том, что типы находятся в другой сборке, поэтому я не верю, что могу вызвать Activator.CreateInstance - person user48408; 04.02.2009
comment
Пока сборка правильно загружена, это не должно быть проблемой. - person Konrad Rudolph; 04.02.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();
}
person Chaowlert Chaisrichalermpol    schedule 04.02.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" } );
person baretta    schedule 04.02.2009

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

person user48408    schedule 04.02.2009

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

person mqp    schedule 04.02.2009

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

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