С# отражение с динамическим классом

Мне нужно выполнить метод "FindAll" на моей странице. Этот метод возвращает список объектов.

Это мой метод, который я выполняю "FindAll". FindAll требует int и возвращает список этих классов.

public void ObjectSource(int inicio, object o)
{
  Type tipo = o.GetType();
  object MyObj = Activator.CreateInstance(tipo);
  object[] args = new object[1];
  args[0] = inicio;
  List<object> list = new List<object>();
  object method = tipo.InvokeMember("FindAll", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, args);
}

Когда я запускаю ObjectSource, он возвращает ok, но я не могу получить доступ к результату. В VS2008 я могу визуализировать список с помощью «ctrl + Alt + q», но приведение не работает.

Забыл сказать: этот метод "НайтиВсе" статичен!


person Tiago Schäffer    schedule 13.11.2009    source источник
comment
Почему вы создаете новый экземпляр типа, почему вы создаете List<object> и не используете его, и почему вы фактически игнорируете возвращаемое значение метода?   -  person Jon Skeet    schedule 13.11.2009
comment
И: зачем создавать общий список‹T› и вставлять в него объект?   -  person Wim Hollebrandse    schedule 13.11.2009
comment
Почему вы создаете новый экземпляр типа? Не используется, удаляю. почему вы создаете объект списка и не используете его? только для теста. Метод FindAll возвращает IEnumerable, но я использую гентерикс, как опубликовал Вим Холлебрандсе. почему вы фактически игнорируете возвращаемое значение метода? мне нужен результат этого метода, и я не знаю, как его получить!   -  person Tiago Schäffer    schedule 13.11.2009
comment
Возвращаемое значение хранится в вашей локальной переменной, которую вы неправильно назвали методом, а не в чем-то вроде returnObject.   -  person Wim Hollebrandse    schedule 13.11.2009


Ответы (3)


Здесь происходит несколько вещей, во-первых, ваш метод не возвращает результат.

Во-вторых, когда вы возвращаете объект, ничто не мешает вам выполнить приведение к соответствующему типу в вызывающем коде.

В-третьих, вы можете использовать Generics, чтобы сделать этот метод строго типизированным:

public T ObjectSource<T>(int inicio, T o)
{
  Type tipo = typeof(T);
  object MyObj = Activator.CreateInstance(tipo);
  object[] args = new object[1];
  args[0] = inicio;
  return tipo.InvokeMember("FindAll", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, args) as T; 
}
person Wim Hollebrandse    schedule 13.11.2009
comment
Привет... 1) Этот метод не должен возвращать никакого результата. Это правильно. 2) Метод FindAll возвращает IEnumarable и использует инструкцию yeld. - person Tiago Schäffer; 13.11.2009
comment
@ChepA: Если метод FindAll возвращает IEnumerable (неважно, используется ли yield или нет), то как вы ожидаете получить этот IEnumerable, если он не возвращается из метода ObjectSource? - person Daniel Pryden; 13.11.2009
comment
Кроме того, как указал Джон Скит в своем комментарии к этому вопросу, создание нового экземпляра объекта, вероятно, здесь неправильно. Разве вы не хотите вызывать FindAll для объекта o? - person Daniel Pryden; 13.11.2009
comment
Как вы сказали, FindAll RETURNS IEnumerable... который в вашем случае вы даже не можете получить, поскольку ваш метод возвращает void. Персиковый. - person Wim Hollebrandse; 13.11.2009
comment
Я изменил свой метод как Wim sad, используя дженерики и ту же структуру. Я не понимаю, почему ObjectSource должен что-то возвращать, ведь этот код — начало. Мне нужны возвраты FindAll для заполнения моей сетки. Как я могу получить возврат FindAll? - person Tiago Schäffer; 13.11.2009
comment
@ChepA: Вы звоните ObjectSource, который, в свою очередь, звонит FindAll. Поскольку вызов FindAll находится внутри метода ObjectSource, единственный способ для кода, который вызывает ObjectSource, получить возвращаемое значение FindAll, — передать возвращаемое значение ObjectSource. Самый простой способ для ObjectSource — просто вернуть возвращаемое значение из FindAll. См. мой ответ для примера кода, который делает именно это. - person Daniel Pryden; 13.11.2009
comment
Вернемся к основам в этом, кажется. - person Wim Hollebrandse; 14.11.2009

Попробуйте это (обновлено):

public IEnumerable ObjectSource(int inicio, object o) {
    Type type = o.GetType();
    object[] args = new object[] { inicio };
    object result = type.InvokeMember("FindAll", 
        BindingFlags.Default | BindingFlags.InvokeMethod, null, o, args);
    return (IEnumerable) result;
}

Лучшим решением было бы поместить ваш метод FindAll в интерфейс, скажем, IFindable, и заставить все ваши классы реализовывать этот интерфейс. Затем вы можете просто привести объект к IFindable и вызвать FindAll напрямую — никакого отражения не требуется.

person Daniel Pryden    schedule 13.11.2009
comment
+1 за предложение интерфейса, я подозреваю, что это гораздо лучшее решение - person Pharabus; 13.11.2009
comment
Хорошая идея, но всегда, когда я привожу результат, возвращает ноль. - person Tiago Schäffer; 13.11.2009
comment
Когда я выполняю object result = o.InvokeMember(FindAll, BindingFlags.Default | BindingFlags.InvokeMethod, null, null, args); тип возвращаемого значения — {FrameWork.Patrimonio.Bem.FindAll}. - person Tiago Schäffer; 13.11.2009
comment
@ChepA: Возможно, тогда вам следует опубликовать исходный код в вашем методе FindAll. - person Daniel Pryden; 13.11.2009
comment
@ChepA: Не делайте o.InvokeMember, это была опечатка с моей стороны, извините. Вместо этого сделайте type.InvokeMember. Это работает? - person Daniel Pryden; 13.11.2009
comment
Кроме того, можете ли вы опубликовать пример того, как вы вызываете метод ObjectSource? Как вы передаете аргумент o? - person Daniel Pryden; 13.11.2009
comment
@Daniel: у меня есть несколько объектов, которые мне нужно привязать к сетке, и этот список содержит более 1000 записей, затем я хочу разбить на 50, и этот объектный источник должен быть универсальным, потому что он вызовет FindAll классов! - person Tiago Schäffer; 16.11.2009
comment
@ChepA: Опубликуйте этот комментарий как отдельный вопрос, и я дам вам пример кода, как это сделать. (И кто-то другой, вероятно, даст вам лучший ответ.) - person Daniel Pryden; 16.11.2009
comment
хорошо..... я сделал это. Когда я выполняю myType.GetMethods(), он возвращает {System.Collections.Generic.IEnumerable1[FrameWork.Patrimonio.Bem] FindAll(Int32)}, why the compiler put "1? - person Tiago Schäffer; 17.11.2009
comment
@ChepA: Поскольку FindAll на самом деле не возвращает IEnumerable, он возвращает IEnumerable<FrameWork.Patriomonio.Bem>. Компилятор использует нотацию `1`, чтобы отличить универсальный IEnumerable<> от неуниверсального IEnumerable. - person Daniel Pryden; 17.11.2009

Дэниел, у меня есть несколько объектов, которые мне нужно привязать к сетке, и этот список содержит более 1000 записей, затем я хочу разбить на 50, и этот объектный источник должен быть универсальным, потому что он вызовет FindAll классов!

person Tiago Schäffer    schedule 17.11.2009
comment
Когда я сказал опубликовать это как отдельный вопрос, я имел в виду, что нужно щелкнуть ссылку «Задать вопрос» в верхней части страницы и задать совершенно новый вопрос. То, что вы разместили здесь, является ответом на ваш собственный вопрос, который на самом деле просто поднимает новый вопрос. Помните, StackOverflow — это не универсальный форум, а сайт вопросов и ответов. - person Daniel Pryden; 17.11.2009
comment
LoL... Но я поработал над размышлениями! Я очень ценю помощь. - person Tiago Schäffer; 18.11.2009