Приведение объекта я получаю через отражение - PullRequest
1 голос
/ 27 октября 2009

У меня есть эта функция:

Программа 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);
}

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

Есть предложения?

Ответы [ 5 ]

3 голосов
/ 27 октября 2009

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 голосов
/ 27 октября 2009

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

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. Вы не получаете безопасность типов. Таким образом, способ ООП состоит в том, чтобы все интерфейсы были в отдельной сборке (на которую ссылаются программа A и программа B):

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

public interface IReportLocationInfo
{
     void SomeMethod();
} 

А затем внедрите ваши бетонные заводы в «подключаемые» сборки ( программа A ):

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

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

0 голосов
/ 27 октября 2009
Activator.CreateInstance(typeof(List<>).MakeGenericType(yourtype)) as IList

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

0 голосов
/ 27 октября 2009

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

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

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

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

0 голосов
/ 27 октября 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...