2009-10-27 2 views
1

У меня есть эта функция:Кастинг объект я получаю через отражение

Программа A

public ICollection<ReportLocationInfo> GetAllReportsInstalled() 
{ 
    return _Reports; 
} 

Я зову его через отражение динамически:

Программа B

internal ICollection<Object> Scan(string path) 
{ 
    MethodInfo GetReports = 
      _reportFactoryType.GetMethod("GetAllReportsInstalled"); 

    return (List<Object>)GetReports.Invoke(_reportFactory, null); 
} 

Я перечисляю список, потому что у меня нет ReportLocationInfo по адресу Программа B, и у меня есть моя собственная функция перевода. Это, конечно, не работает.

Любые предложения?

+0

Как вы получите доступ к этим данным, если вы не можете получить доступ к классу «ReportLocationInfo» в программе B? – Groo

+0

Info.GetType(). GetProperty ("propertyName") Но у меня есть еще одна проблема: как мне получить доступ к каждому списку ReportInfo из списка? – Sarit

ответ

3

ICollection<T> реализует System.Collections.IEnumerable. Вы можете использовать этот интерфейс, а затем использовать foreach для итерации по вашим объектам.

MethodInfo GetReports = _reportFactoryType.GetMethod("GetAllReportsInstalled"); 
IEnumerable reports = (IEnumerable)GetReports.Invoke(_reportFactory, null); 

foreach (object report in reports) 
{ 
    // Use reflection to read properties or add to a new List<object> if you 
    // need an ICollection<object> 
} 
0

Вы не сможете использовать класс, который вы не определили в текущей сборке или сборках, на которые ссылается текущая сборка. Нет никакого способа обойти это; по этой причине.

Вы сказали, что хотите, чтобы он переводился динамически, я предполагаю, что вы хотите, чтобы он смог получить Intellisense, хотя класс еще не определен, ну, это просто невозможно.

+0

Я знаю, поэтому я хочу динамически переводить его на свою сторону. Возможно ли это? Как? – Sarit

0
Activator.CreateInstance(typeof(List<>).MakeGenericType(yourtype)) as IList 

Я не уверен, что вы пытаетесь сделать правильно. Как может ReportInfo внезапно изменить на ReporttLocationInfo?

+0

Вы правы, моя ошибка. Я отредактировал это. Я хочу ReportLocationInfo в Object, потому что ReportLocationInfo не существует в ProgramB. Это можно сделать? – Sarit

0

Прежде всего, вы действительно не хотите этого делать.

Если вы настаиваете, вам нужно будет проверить возвращаемое значение вашего запроса GetReports.Invoke через отражение. Начать с:

Object reports = GetReports.Invoke(_reportFactory, null); 

работы оттуда, зная, что сообщения на самом деле типа ICollection<ReportLocationInfo>

0

Простой способ будет:

private ICollection<object> ScanInternal(string path) 
{ 
    List<object> result = new List<object>(); 

    MethodInfo GetReports = 
      _reportFactoryType.GetMethod("GetAllReportsInstalled"); 

    IEnumerable reports = GetReports.Invoke(_reportFactory, null) 
      as IEnumerable; 

    if (reports != null) // or exception if null ? 
    { 
     foreach (object report in reports) 
      result.Add(report); 
    } 

    return result; 
} 

Но более подходящим способом было бы создать интерфейс в отдельном совместно сборе (например, IReportLocationInfo), а затем использовать этот интерфейс в оба сборок.

Рассмотрите возможность реорганизации своего кода для достижения этого, потому что методы вызова с использованием Reflection на экземпляре object почти похожи на обычный C. Вы не получаете безопасности типа.

Таким образом, ООП путь будет иметь все интерфейсы в отдельную сборку (на которую ссылается как программа А и программа В):

public interface IReportFactory 
{ 
    IEnumerable<IReportLocationInfo> GetAllReportsInstalled(); 
} 

public interface IReportLocationInfo 
{ 
    void SomeMethod(); 
} 

А потом реализовать свои конкретные заводы внутри «plug- в»сборки (программа А):

public class MyReportFactory : IReportFactory 
{ 
    // ... 
} 

А затем отливали каждый плагин к IReportFactory после загрузки внутри программа B.

Смежные вопросы